Using accumarray or a similar method for tables
7 views (last 30 days)
Show older comments
Hello,
I have a table with the 1st column being numeric date/time information, and the rest of the data columns (dozens of them) being numeric. The time interval for each row of data is approx. 1 second, but I would like to calculate the minute-averaged value. I’ve converted my table to an array and have mostly followed the help here: https://www.mathworks.com/matlabcentral/answers/81203-convert-10-minute-average-to-hourly, however the “accumarray” function doesn’t work for a matrix. Instead, I have a “for” loop for each column, where accumarray operates on each column. I would like to eliminate this “for” loop because it can be slow when I have days of data to process. Can someone please tell me if there is another method to do this, or if there is a command for tables that would do this automatically? (I thought about using a table grouping variable, however I think this would just group my data into 60 rows – 1 for each minute.)
Here is my code that I have, and thank you in advance for your help.
data = table2array(MyData); % table to array
date1 = datevec(data(:,1)); % date/time matrix
[a,~,c] = unique(date1(:,1:5),'rows'); % returns each unique row of date1 looking only up to minutes
out(:,1:6)=[a,zeros(size(a,1),1)]; % first 5 columns are yr, mnth, day, hr, min from unique function above, 6th column is sec (0s)
for i=1:width(MyData)-1 % loop over each data column
out(:,i+6) = accumarray(c,data(:,i+1),[],@mean); % ith col is average value over minute
end
0 Comments
Answers (3)
Steven Lord
on 26 Nov 2024
This wasn't an option in the release the original poster was using (the two functions required were released in release R2016b, which came out a few months after this question was asked) but today I suggest turning your table into a timetable using table2timetable then call retime on the resulting timetable.
0 Comments
Sean de Wolski
on 25 Jul 2016
% fake c and data
c = [1; 2; 2; 1; 3]
data = repmat(1:6,5,1)
% engine
sz = size(data)
accumarray([repmat(c,sz(2),1), repelem((1:sz(2))',sz(1),1)],data(:),[],@mean)
Take advantage of the fact that subs can be two dimensional.
0 Comments
Patrick
on 26 Nov 2024
Moved: Walter Roberson
on 26 Nov 2024
Since 2018 you can just use groupsummary on the datetime column to get the minute average
% Make a dataset
times = [datetime(2020,01,01,00,00,00):seconds(1):datetime(2020,01,01,01,00,00)].';
data1 = rand(length(times),1);
data2 = rand(length(times),1);
tableData = table(times,data1,data2);
groupedTable = groupsummary(tableData,"times","minute","mean")
To do this with arbitrary time intervals, you can use histcounts on your table.datetime column to correctly bin the times, add the bin values to the table, and use groupsummary on the bin column
% Bin times however you want
binWidth = seconds(120);
edges = datetime(2020,01,01,00,00,00):binWidth:datetime(2020,01,01,01,00,00);
[~,~,bins] = histcounts(tableData.times,edges);
% Add the times to the table
tableData = addvars(tableData,bins);
% Group by bins
groupedTable = groupsummary(tableData,"bins","mean")
0 Comments
See Also
Categories
Find more on Tables in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!