How can I use table() with a variable number of columns?
10 views (last 30 days)
Show older comments
I'm making a set of tables from a 4x4x4 array, like so:
T{jj} = table(data(jj,:,1)',data(jj,:,2)',data(jj,:,3)',data(jj,:,4)','VariableNames',colName,'RowNames',rowName);
The annoying thing is, I have to change this line every time there's a different number of columns. For example, for 3 columns, the command is:
T{jj} = table(data(jj,:,1)',data(jj,:,2)',data(jj,:,3)','VariableNames',colName,'RowNames',rowName);
I know I could do a switch on the number of columns and have a case for every possible number of columns I might ever have, but is some way around that? The obvious solution of giving it the data as an array doesn't work if you want named rows and columns:
T{jj} = table(data(jj,:,:),'VariableNames',colName,'RowNames',rowName);
Error using table (line 369)
The VariableNames property must contain one name for each variable in the table.
I get the exact same error back if I use slice():
T{jj} = table(slice(data(jj,:,:)),'VariableNames',colName,'RowNames',rowName);
But it works fine without row / column names
T{jj} = table(data(jj,:,:));
Am I missing something simple, or is this maybe a design oversight?
4 Comments
Stephen23
on 4 Jun 2025
"I see what you're doing, the permute() sets B up so that we can say B(:,:,1) instead of squeeze(A(1,:,:))."
The code in my comment is completely tangential to the question of robustness, it just shows an alternative approach to solve this problem (sometimes posters on this forum appreciate being shown other approaches that they have not considered, or alternative ways to design their data, etc.).
Of course you can apply PERMUTE to each column separately, exactly as you did with SQUEEZE:
A = rand(2,5,4);
C{1} = array2table(permute(A(1,:,:),[2,3,1]), VariableNames="x"+(1:4));
C{2} = array2table(permute(A(2,:,:),[2,3,1]), VariableNames="x"+(1:4));
C{:}
A(2,:,1).' % for comparison: the first column of the second table
"But I'm not clear on why that's more "robust"... What does it buy us?"
PERMUTE buys you the guarantee that input dimensions will end up being permuted into the dimensions that are specified, which SQUEEZE does not. Consider the code you showed in your comment here:
What happens one day the input data just happens to have only one column? Lets try it:
A = rand(2,1,4);
array2table(permute(A(1,:,:),[2,3,1]), VariableNames="x"+(1:4)) % PERMUTE -> robust
array2table(squeeze(A(1,:,:)), VariableNames="x"+(1:4)) % SQUEEZE -> error
Accepted Answer
Star Strider
on 3 Jun 2025
Something like this seems to work --
data = randn(2,5,4);
jj = 1;
T{jj} = array2table(squeeze(data(jj,:,1:3)), VariableNames=compose('Variable %2d',1:3));
jj = 2;
T{jj} = array2table(squeeze(data(jj,:,1:4)), VariableNames=compose('Variable %2d',1:4));
T{1}
T{2}
.
2 Comments
More Answers (2)
the cyclist
on 3 Jun 2025
I assume that data, colName, and rowName are consistently dimensioned.
slice = squeeze(data(jj,:,:));
TT{jj} = array2table( slice,'VariableNames',colName,'RowNames',rowName);
4 Comments
the cyclist
on 3 Jun 2025
Hm. This worked for me (and gave the same result as your syntax).
rng default
N = 4;
data = rand(N,N,N);
jj = 1;
colName = {'c1','c2','c3','c4'};
rowName = {'r1','r2','r3','r4'};
slice = squeeze(data(jj,:,:)); % this becomes an [nRows × nVars] matrix
TT{jj} = array2table( slice, ...
'VariableNames', colName, ...
'RowNames', rowName )
Image Analyst
on 4 Jun 2025
@Jerry Guern, perhaps this will clear things up:
% Get last dimension.
data = randn(4,4,4); % Create a 3-D array
slice1 = data(:, :, 1); % A 2-D array
whos slice1
% Get middle dimension.
array2 = data(:, 1, :); % A 3-D array
whos array2
slice2 = squeeze(array2); % Collapse singleton dimension to make it a 2-D slice
whos slice2
% Get first dimension.
array3 = data(1, :, :); % A 3-D array
whos array3
slice3 = squeeze(array3); % Collapse singleton dimension to make it a 2-D slice
whos slice3
Image Analyst
on 3 Jun 2025
Yes, you're going to have to do something. If you have more variables that you want to add to a column or columns you want to remove, it won't telepathically know that you want to do it unless you tell it, and tell it how, so you're going to have to do something. Either make up the table brand new, or use functions to change the number of columns.
Try using addvars, removevars, and movevars - maybe they'll be easier for you. Maybe make up just one column and add the others in a loop with addvars until they're all added. Unless you have a very small amount like 2-4 columns it's easier to use a for loop than an if-else block to form the exact table you want.
2 Comments
Image Analyst
on 4 Jun 2025
OK, from your initial post and the other posts, I guess I misunderstood, thinking you wanted a table, but it appears you actually want a cell array with tables inside the cells.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!