Combine multiple varying length double arrays into one timetable
41 views (last 30 days)
Show older comments
I have a .mat file with multiple (a few thousand) individual 2-column double arrays, all named for a different variable.
These arrays are of varying length (from a few to a few million rows), but for each of them the first column always is the timestamp in datenum format, the second column is the data.
I would like to get them into a single timetable where each column is the data from each array, with the column name taken from the variable name.
e.g.
log.mat
> Var1
> Time
> Data
> Var2
> Time
> Data
...
> VarN
> Time
> Data
into
Workspace
> TT
> Time
> Var1
> Var2
...
> VarN
I assume there has to be a better way of doing this than iteratively calling each variable from the .mat file, concatentating horizontally into one huge array, and then following this guide to convert it to a timetable?
1 Comment
dpb
ungefär en timme ago
Pretty much @Voss gave the way; the problem is you have variable-length data arrays and a table or timetable must have same number of elements for each variable. This means you'll have to pad the shorter to the length of the longer.
And, unless the various variables also have consistent tmestamps, you'll also have to then synchronize the times to put the same variables at the same time in the table.
You can avoid having to write each variable name directly by using the functional form for load and return the variables as a struct, then you can iterate over the fieldnames in the stuct.
Answers (2)
Stephen23
on 20 Dec 2024 at 15:00
Edited: Stephen23
on 20 Dec 2024 at 16:21
"I assume there has to be a better way of doing this than iteratively calling each variable..."
Note that synchronize accepts 1..N input timetables, which means you can synchronize all of them in one go. And that is probably what you should do, using a simple comma-separated list.
Fake data:
F1 = @(n) [datenum(2024,12,20,1,2,fix(600*rand(n,1))/10),randi(9,n,1)];
S.Var1 = F1(13);
S.Var2 = F1(1e2);
S.Var3 = F1(23)
Of course in your actual code you would LOAD into an output variable (which you should be doing anyway):
S = load(..);
Then synchronize:
F2 = @(a) array2timetable(a(:,2),'RowTimes',datetime(a(:,1),'ConvertFrom','datenum'));
C = struct2cell(structfun(F2,S, 'UniformOutput',false))
T = synchronize(C{:});
T.Properties.VariableNames = fieldnames(S)
0 Comments
Star Strider
ungefär en timme ago
Edited: Star Strider
11 minuter ago
First, convert the datenum values to datetime arrays using the ConvertFrom='datenum' name-value pair, either reading each of them in as a timetable using the readtimetable function,or reading them in as a table and then using thee table2timetable function to convert them. I’m not certain what you want to do after that, however if I understand your question correctly, the synchronize function would be my approach. This can be done in a sinngle synchronize call, or it may be necesary to do this in a loop, adding each new timetable in each iteration.
EDIT — (20 Dec 2024 at 14:37)
That approach would look something like this —
TT{1} = timetable(datetime(2024,12,18)+hours(sort(rand(10,1)*10)), randn(10,1), VariableNames={'Voltage 1'});
TT{2} = timetable(datetime(2024,12,18)+hours(sort(rand(12,1))*10+4), randn(12,1), VariableNames={'Voltage 2'});
TT{3} = timetable(datetime(2024,12,19)+hours(sort(rand(8,1))), randn(8,1), VariableNames={'Voltage 3'});
for k = 1:numel(TT)
disp("height(TT{"+k+"} = "+height(TT{k}))
disp(TT{k})
end
TT_Combined = TT{1};
for k = 2:numel(TT)
TT_Combined = synchronize(TT_Combined, TT{k});
end
disp("size(TT_Combined = ["+size(TT_Combined,1)+" "+size(TT_Combined,2)+"]")
disp(TT_Combined)
Another approach could be:
TT_Combined = synchronize(cat(1,TT{:}))
However this synchronizes them all in to one timetable with one variable, not separate variables, so all the variable names would have to be the same.
.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!