How do I get a function in a for loop so it applies it to an entire table?
1 view (last 30 days)
Show older comments
My code:
t = timetable2table(tt);
t2=t(:,1:2); % here it takes only one station out of a table
t2.Year= dateshift(t.Date,'start','year'); % Here I create a seperate date column, which takes out the time from the date column
rowfun(@myFun,t2,'GroupingVariable','Year','OutputVariableNames',{'Max' 'MaxX'}) % Here it finds the maximum of each year (of one station) and the time the maximum occurred
function [tmax,xmax] = myFun(t,x)
[xmax,imax] = max(x,[],1);
tmax = t(imax);
end
How do I get this to loop for each station so it finds the maximum for each year for each station and the time the maximum occurred?
5 Comments
Cris LaPierre
on 12 Mar 2021
Edited: Cris LaPierre
on 12 Mar 2021
You don't want rowfun. Rowfun assumes each column of your table is an input to your function, and is applied to each row separately. You kind of want the exact opposite, meaning you want it to look at all rows, and apply to each column separately.
While groupsummary can help you find the yearly max for each station without a loop, to get the corresponding timestamp for each station likely will.
Since it's much easier to test with actual data, consider sharing your table. Save it to a mat file and attach it to your post using the paperclip icon.
Accepted Answer
Cris LaPierre
on 12 Mar 2021
Edited: Cris LaPierre
on 12 Mar 2021
To follow up, the easiest way to find yearly max is to use groupsummary with the appropriate settings.
load matlabworkspace28.02.mat
yrMax = groupsummary(tt,"Kuupev","year","max",'IncludeMissingGroups',false)
However, this will not give you the corresponding timestamp for each max. There is no slick way I could think of to do that, so here's my brute force attempt.
% Find the years in the timetable
Y = min(year(tt.Kuupev)):max(year(tt.Kuupev));
% create a new table to hold the results
yrTbl = array2table(NaT(length(Y),2*width(tt)),"VariableNames",["Date" "Station"]' + (1:width(tt)));
yrTbl = convertvars(yrTbl,2:2:width(yrTbl),@datenum);
% loop through each year
for y = 1:length(Y)
% find the max value for each station plus the corresponding index
dateInd = find(year(tt.Kuupev)==Y(y));
[val,ind] = max(tt{dateInd,:});
% Assign values to output table
C = 1:2:width(yrTbl);
yrTbl{y,C} = tt.Kuupev(dateInd(ind))';
yrTbl{y,C+1} = val;
% If max is NaN, set time to NaT
yrTbl{y,C(isnan(val))} = NaT;
end
% View results
yrTbl
2 Comments
Cris LaPierre
on 12 Mar 2021
You should inspect the data for that year at that station. You might find the answer makes sense.
More Answers (3)
Prudhvi Peddagoni
on 12 Mar 2021
Edited: Prudhvi Peddagoni
on 12 Mar 2021
Hi,
First, run a for loop over all the rows of data to take note of the indices of each year. For more info about table indexing, refer this
indices = zeros(1,9); % stores starting indices of years
currentYear = 2011;
for idx = 1:length(t)
if year(t.Date(idx)) == currentYear
currentYear = currentYear+1;
indices(currentYear-2011) = idx;
end
end
After this, use a for loop to go over each year. For each year, extract the rows of that year from the table to a matrix. Then give that matrix to the max function like this:
[maxValues, correspondingIndices] = max(matrix,[],2);
After getting the indices, you can get the corresponding date from the table.
Hope this helps.
0 Comments
Allen
on 12 Mar 2021
Edited: Allen
on 12 Mar 2021
A relatively general approach to extract max values by year for each table variable (stations in this case) assuming the first variable of the table is a datetime value.
t = timetable2table(tt);
Vars = t.Properties.VariableNames; % Extract Variable Names
Yrs = unique(year(t.(Vars{1}))); % Get unique year values, using t.(Vars{1}) instead of t.Date since data provided had non-English labels.
Yrs(isnan(Yrs)) = []; % Remove NaN values
% Loop for each year and find max value for all stations
xmax = zeros([length(Yrs),length(Vars)-1]); % Pre-allocate for speed
for i=1:length(Yrs)
xmax(i,:) = max(t{year(t.(Vars{1}))==Y(i),2:end});
end
% Convert results to table
tmax = array2table([Yrs,xmax],'VariableNames',Vars);
Seth Furman
on 22 Mar 2021
To add to Chris' answer, you can also find the yearly max for each station using retime. For example, using the first two columns of the timetable you provided
>> load matlabworkspace28.02.mat
>> ttMax = retime(tt(:,1:2),'yearly','max')
ttMax =
9×2 timetable
Kuupev AJHAAP01 AJHARK01
___________ ________ ________
01-Jan-2011 11.3 15.8
01-Jan-2012 31.3 13.7
01-Jan-2013 44.8 18.5
01-Jan-2014 16.6 12
01-Jan-2015 9.2 10
01-Jan-2016 11.6 21
01-Jan-2017 10.3 23.8
01-Jan-2018 16 15.7
01-Jan-2019 14 13.1
0 Comments
See Also
Categories
Find more on Dates and Time 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!