Table of Tables or cell of Tables

Hi,
I am preforming machine learning on 13 channels of data and am currently at the feature extraction stage. I have created 13 seperate tables and now which to bring these together into one variable.
I had been trying to create a 1*13 table in which each table element was another table, however I cannot get this to work. I have been able to create a 1*13 cell with each cell element being a table instead. My question is this, is there any benifit to using a tables within cells over tables within tables and vice versa. I will also include some code below, I would like to know how to also make this work for tables within tables too for furture use!
filesTable = array2table(fileNames); % Generate file names to identify each entry
sTruthBuffer = sTruthBuffer';
truthTable = array2table(sTruthBuffer); % Generate ground (clinical) truth
channels = cell(13,1); % generate empty cell for later
for i = 1:13 % For each of the 13 channels
actTable = rows2vars(array2table(act(:,:,i))); % act(ivity) is a 1*2538*13 double
actTable = removevars(actTable,'OriginalVariableNames'); % remove the orignal variale names as junk
actTable.Properties.VariableNames = {'Activity'} % Rename column as something sensible
mobTable = rows2vars(array2table(mob(:,:,i))) % mob(ility) is a 1*2538*13 double
mobTable = removevars( mobTable,'OriginalVariableNames');
mobTable.Properties.VariableNames = {'Mobility'}
complxTable = rows2vars(array2table(complx(:,:,i))) % complx(ity) is a 1*2538*13 double
complxTable = removevars(complxTable,'OriginalVariableNames');
complxTable.Properties.VariableNames = {'Complexity'}
channel = [filesTable,actTable,mobTable,complxTable,truthTable]; % Concatinate all the tables into one table 'channel'
channels{i} = channel ; % for each channel write the generated table 'channel' into a cell array called 'channels',
% this is okay but I think a nested table would be easier to work with?
end

 Accepted Answer

Hi Christopher,
I had been trying to create a 1*13 table in which each table element was another table, however I cannot get this to work.
  • What is your reason for wanting to store these 13 tables in a single 1x13 table? Are you doing this because you want to have a label for each table?
  • Where are you getting stuck? Is the issue that the tables are different heights? Table variables must have the same height, but one way to get around this is to put the tables in cell arrays, e.g.
t1 = table([1;2;3]);
t2 = table([1;2]);
table({t1}, {t2}, 'VariableNames', ["MyLabel1", "MyLabel2"])
ans = 1×2 table
MyLabel1 MyLabel2 ___________ ___________ {3×1 table} {2×1 table}
It's also worth mentioning that you can store additional metadata in the UserData property of each table, e.g.
t1.Properties.UserData = "MyLabel1";
t2.Properties.UserData = "MyLabel2";
{t1, t2}
ans = 1×2 cell array
{3×1 table} {2×1 table}

5 Comments

Hi Seth,
Thank you for getting back to me!
I will try and make my question a bit clearer.
  • I want to store this as 13 seperate tables as each table represents extracted features of 1 different channel. Keeping the tables in a per channel basis should allow me easier indexing over meta data lables. If I combine all the data from diffrent channels into one table with lables, the indexing will be quite difficult to manage. Each of the tables are the same dimention, with the idea being that I will subsiquenlty run the feature extraction algoritum over ~1000 files and append the new features on a per file per channel basis to these 13 tables.
  • In terms of my problem, currently the code above creates a cell array of tables, but I would like a table of tables. I cannot figure out how to make 'channels' a 1x13 table so it is currently a 1x13 cell array. (I will include a sample copy of channels, it is all opensource from physionet data anyways). I belive that it would be easier and more intuitive to use table of tables as the calls are the same rather than having to mix and match cell and table calls.
Thank you again for your help, hopefull this clears up some of what I am trying to do!
Christopher
Hi Seth,
In addition to the comment above ^ (I tried to edit but it was taking a while to load) I want to use the classification learner app which will not allow for cells to be imported. Therefore I must use a table, hopefully I can also use table of tables!
Christopher
As a side note, given an array X
rng default
X = randi(1000, [1 2538]);
creating a table from X and then transposing it
t = rows2vars(array2table(X));
removevars(t, "OriginalVariableNames")
ans = 2538×1 table
Var1 ____ 815 906 127 914 633 98 279 547 958 965 158 971 958 486 801 142
can be written more simply (and efficiently) by transposing X before we create the table
t = array2table(X')
t = 2538×1 table
Var1 ____ 815 906 127 914 633 98 279 547 958 965 158 971 958 486 801 142
Christopher, please let me know which of the following workflows meet your requirements and why. From your description it sounds like indexing syntax is most important to you, in which case (2) and (3) seem like they should be the most convenient.
1) Storing the channels as separate elements of a cell array
% Create sample data
rng default
act = 1000 * rand(1, 2538, 5);
mob = 1000 * rand(1, 2538, 5);
complx = 1000 * rand(1, 2538, 5);
% Preallocate a template channel
channel = table('Size', [2538 3], 'VariableTypes', ["double","double","double"], ...
'VariableNames', ["Activity","Mobility","Complexity"]);
% Preallocate 5 channels by copying 'channel'
channels = repmat({channel}, 1, 5);
% Populate channels
for i = 1:length(channels)
channels{i}.Activity = act(:,:,i)';
channels{i}.Mobility = mob(:,:,i)';
channels{i}.Complexity = complx(:,:,i)';
end
channels
channels = 1×5 cell array
{2538×3 table} {2538×3 table} {2538×3 table} {2538×3 table} {2538×3 table}
channels{1}.Activity
ans = 2538×1
814.7237 905.7919 126.9868 913.3759 632.3592 97.5404 278.4982 546.8815 957.5068 964.8885
2) Storing the channels as sub-tables
% Preallocate a template channel
channel = table('Size', [2538 3], 'VariableTypes', ["double","double","double"], 'VariableNames', ["Activity","Mobility","Complexity"]);
% Preallocate 5 channels by copying 'channel'
channels = repmat(table(channel), 1, 5);
channels.Properties.VariableNames = "Channel_" + (1:width(channels));
% Populate channels
for i = 1:width(channels)
channels.(i).Activity = act(:,:,i)';
channels.(i).Mobility = mob(:,:,i)';
channels.(i).Complexity = complx(:,:,i)';
end
head(channels)
ans = 8×5 table
Channel_1 Channel_2 Channel_3 Channel_4 Channel_5 Activity Mobility Complexity Activity Mobility Complexity Activity Mobility Complexity Activity Mobility Complexity Activity Mobility Complexity __________________________________ __________________________________ __________________________________ __________________________________ __________________________________ 814.72 949.91 441.85 877.63 417.46 245.85 768.77 986.38 926.66 548.45 719.43 144.62 181.33 720.86 444.1 905.79 173.42 640.23 469.1 844.88 793.38 388.08 623.95 407.95 9.5179 902.01 951.38 946.59 557.23 791.41 126.99 0.9046 220.18 437.42 551.51 903.76 453.26 596.26 16.093 828.36 195.18 152.9 100.85 449.51 546.85 913.38 878.46 49.502 746.18 813.15 907.45 132.85 577.29 88.012 908.54 897.67 39.922 388.04 345.53 414.56 632.36 850.54 210.45 467.91 315.4 225.58 758.51 403.03 705.9 705.3 821.61 387.15 289.22 60.251 229.84 97.54 336.41 864.19 860.83 859.36 334.14 565.24 545.45 899.41 243.33 665.95 288.97 73.087 444.04 213.81 278.5 98.33 110.84 466.51 217.37 16.859 648.64 777.43 829.93 589.23 656.68 339.9 194.61 220.88 806.04 546.88 628.12 964.97 498.1 115.36 417.57 798.06 470.4 485.04 938.9 535.54 658.7 417.49 724.76 942.14
channels.Channel_1.Activity
ans = 2538×1
814.7237 905.7919 126.9868 913.3759 632.3592 97.5404 278.4982 546.8815 957.5068 964.8885
3) Storing the channels as pages of a 3-dimensional array
channels = table(pagetranspose(act), pagetranspose(mob), pagetranspose(complx), ...
'VariableNames', ["Activity","Mobility","Complexity"]);
head(channels)
ans = 8×3 table
Activity Mobility Complexity ____________ ____________ ____________ 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double 1×1×5 double
channels.Activity(:,:,1)
ans = 2538×1
814.7237 905.7919 126.9868 913.3759 632.3592 97.5404 278.4982 546.8815 957.5068 964.8885
Hi Seth,
This helped me massively thank you! I went down the approach of (2) storing multiable channels as sub tables, this worked for me as tables are accepted by MATLAB ML tools and what I had failed to realise is that multiple channels should be fed in side by side for ML rather than independetly. I have some initial results from my ML which are as I would expect, now I just have to improve these with additional channel and feature selection. Thank you again for all you help!!!
Christopher

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2020b

Tags

Community Treasure Hunt

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

Start Hunting!