Help preallocating variables for a table

6 次查看(过去 30 天)
Hi everyone,
so i have written some code which goes like this:
function caTable = makeCaTable(caCM)
% creates a table with information about the frames(coordinates of the
% centroids and the total number of cells in the frame)
Frame = {};
PosX = {};
PosY = {};
NumberOfCells = {};
for i = 1:size(caCM,2)
C = chop(caCM{1,i},0);
for j = 1:size(C,1)
Frame{end+1,1} = i;
PosX{end+1,1} = C(j,1);
PosY{end+1,1} = C(j,2);
if(j == 1)
NumberOfCells{end+1,1} = size(C,1);
else
NumberOfCells{end+1,1} = '-';
end
end
end
% write the table
caTable = table(Frame, PosX, PosY, NumberOfCells);
it works and gives me the results i want. But now i want to preallocate the variables. I thought I do it like this:
[nrows,ncols] = cellfun(@size,caCM);
rows = sum(nrows);
Frames = cell(rows,1);
PosX = cell(rows,1);
PosY = cell(rows,1);
NumberOfObjects = cell(rows,1);
But if i do so i cant use my for loop the way i wrote it, since it would always put the values at the end of the preallocated matrices. But if i simply use:
Frames(j,1) = i
my table will not have all the fields. I really don't know how i can fix this. Maybe some of you could help me with that.
Thank you very much!
  2 个评论
Guillaume
Guillaume 2018-9-13
编辑:Guillaume 2018-9-13

Please get rid of all the extra blank lines you've added to the code and in the future use the {}Code button to format code as such, as I've done for you now.

What is C (returned by chop)? A cell array? A matrix?

Why are PosX, PosY and particularly Frame cell arrays. Frame only stores scalar numerics. Not sure about PosX and PosY (depends on what C is).

Julian
Julian 2018-9-13
Thank you Guillaume. C is a matrix with doubles in it. They don't necessarly have to be cell arrays. I just built it that way because it was the first thing that came to my mind. They actually all hold scalar numerics.

请先登录,再进行评论。

采纳的回答

Guillaume
Guillaume 2018-9-13
编辑:Guillaume 2018-9-13
C is a matrix with doubles in it
In that case,
function caTable = makeCaTable(caCM)
%doc goes here
% caCM: a 2D(?) cell array
% caTable:a table with 4 variables: Frame, PosX, PosY, NumberOfCells
chopped = cellfun(@(x) chop(x, 0), caCM(1, :), 'UniformOutput', false)'; %transpose for easier repelem and cell2mat
NumberOfCells = cellfun(@(m) size(m, 1), chopped);
NumberOfCells = repelem(NumberOfCells , NumberOfCells );
Frame = repelem((1:size(chopped, 1))', NumberOfCells);
chopped = cell2mat(chopped);
PosX = chopped(:, 1);
PosY = chopped(:, 2);
caTable = table(Frame, PosX, posY, NumberOfCells);
end
As a rule you shouldn't be using cell arrays unless you need to, they're slower to process and takes a lot more memory than a matrix (15 times more if each cell is just a scalar double).
Note that I'm replicating the number of cells for all rows of a frame instead of having '-' for all rows but the first of the frame. It's rarely a good idea to mix numbers and characters in a variable. If you want a different value for all but the first row, I'd recommend using NaN instead. It's trivially done:
NumberOfCells = repelem(NumberOfCells, NumberOfCells); %continuing on from there
NumberOfCells([false; diff(NumberOfCells) == 0]) = NaN;
If you really want a '-', then it's slightly more complicated:
ncells = repelem(NumberOfCells, NumberOfCells);
NumberOfCells = num2cell(ncells);
NumberOfCells([false; diff(NumberOfCells) == 0]) = {'-'};
  5 个评论
Guillaume
Guillaume 2018-9-13

No, I understood the intent the first time round. It's my mistake, I meant to use the original NumberOfCell before it got repelem'd on that Frame line. Swapping the order of the two lines will fix the error:

   NumberOfCells = cellfun(@(m) size(m, 1), chopped);
   Frame = repelem((1:size(chopped, 1))', NumberOfCells);    %to be done first
   NumberOfCells = repelem(NumberOfCells , NumberOfCells);

Better would be not to reuse NumberOfCells for different purpose so replace the above three by:

ncells = cellfun(@(m) size(m, 1), chopped);
NumberOfCells = repelem(ncells, ncells);
Frame = repelem((1:size(chopped, 1))', ncells);

and then the order doesn't matter.

Julian
Julian 2018-9-13
Thank you so much Guillaume. I really learnt a lot! It works just fine now

请先登录,再进行评论。

更多回答(1 个)

Steven Lord
Steven Lord 2018-9-13
I think you want to use the T = table('Size',sz,'VariableTypes',varTypes) syntax shown on the documentation page for the table function.
  2 个评论
Julian
Julian 2018-9-13
编辑:Julian 2018-9-13

Yes i did that:

    [nrows,ncols] = cellfun(@size,caCM);
rows = sum(nrows);
varTypes = {'double', 'double', 'double', 'double'};
varNames = {'Frame', 'PosX', 'PosY', 'NumberOfCells'};
sz = [rows 4];
caTable = table('Size', sz, 'VariableTypes', varTypes, 'VariableNames',varNames);

but I still don't know how to use the for loop to make it fill out the empty fields the right way.

Peter Perkins
Peter Perkins 2018-9-13
The preallocation syntax that Steve is referring to was introduced in R2018a.
But Guillaume's answer avoids needing to preallocate the table, because nothing is growing dynamically, and everything is a vectorized assignment. +1.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Logical 的更多信息

产品


版本

R2018a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by