Monthly maximum in data

6 views (last 30 days)
Max Langworthy
Max Langworthy on 22 Jan 2021
Edited: Max Langworthy on 25 Jan 2021
I am trying to write a function that finds all the monthly maxima for a whole dataset. I am very new to programming and MATLAB. This is an example of a loop similar to the one i am doing
for i=1:100
year(i)=max(d(i))
end
I tried to use this code and copy and paste it for every year in the dataset, because I don't know how to use timetable or double 'for' loops, but I received an error message telling me that the left and right sides have different numbers of elements. How could I rewrite this to give me the function I'm looking for?
  1 Comment
dpb
dpb on 22 Jan 2021
Don't beat head against a wall, convert to a timetable and then use retime
That way will be about two or three lines of code -- there are clear examples in the doc -- give it a go and post back your efforts and where get stuck.

Sign in to comment.

Accepted Answer

Kelly Kearney
Kelly Kearney on 23 Jan 2021
While you could do this with find, using the second output of max is a bit quicker.
% Some fake data similar to yours
t = datetime(2018,1,1:500)';
rsq = [rand(500,1) day(t) month(t) year(t)];
% Find max...
imax = zeros(12,1);
for im = 1:12
tmp = rsq(:,1); % temporary copy of the data
tmp(rsq(:,3)~=im) = -Inf; % anything not matching this month set low
[~,imax(im)] = max(tmp); % returns index of max value
end
maxval = rsq(imax,:)

More Answers (1)

dpb
dpb on 24 Jan 2021
t = datetime(2018,1,1:500)';
rsq = [rand(500,1) day(t) month(t) year(t)];
Alternatively for the same data structure above:
maxVals=splitapply(@max,rsq(:,1),findgroups(rsq(:,3)));
This solution and the one above both will be a global max over all data in the array of the given month -- if there are multiple years of data and it isn't desired to analyze all months of all years as a composite, then must group by both year and month:
[g,idy,idm]=findgroups(rsq(:,4),rsq(:,3));
maxVals=splitapply(@max,rsq(:,1),g)];
For a given set of values here, this resulted in:
[idm idy maxVals]
ans =
1.00 2018.00 0.98
2.00 2018.00 0.97
3.00 2018.00 0.99
4.00 2018.00 0.99
5.00 2018.00 1.00
6.00 2018.00 0.92
7.00 2018.00 0.99
8.00 2018.00 0.91
9.00 2018.00 0.97
10.00 2018.00 0.96
11.00 2018.00 0.95
12.00 2018.00 0.99
1.00 2019.00 0.93
2.00 2019.00 0.96
3.00 2019.00 1.00
4.00 2019.00 0.99
5.00 2019.00 0.96
>>
in a tabular form with the grouping id variables from findgroups. I used format bank to avoid the automatic scaling of default format but that does add the two decimal points onto the integer values...
A table isn't really any harder--starting from the array above,
trsq=array2table(rsq,'VariableNames',{'Data','Day','Month','Year'});
tmaxVals=rowfun(@max,trsq,'InputVariables','Data', ...
'GroupingVariables',{'Year','Month'}, ,,, ...
'OutputVariableNames',{'GroupMax'});
for the same realization of the random data as above this gives:
>> format short,format compact
>> head(trsq)
ans =
8×4 table
Data Day Month Year
_______ ___ _____ ____
0.30596 1 1 2018
0.91988 2 1 2018
0.80037 3 1 2018
0.66754 4 1 2018
0.25832 5 1 2018
0.95717 6 1 2018
0.40822 7 1 2018
0.51435 8 1 2018
>> tmaxVals =
17×4 table
Year Month GroupCount GroupMax
____ _____ __________ ________
2018 1 31 0.98046
2018 2 28 0.96657
2018 3 31 0.99294
2018 4 30 0.99388
2018 5 31 0.99522
2018 6 30 0.92159
2018 7 31 0.98775
2018 8 31 0.91045
2018 9 30 0.9694
2018 10 31 0.95942
2018 11 30 0.9504
2018 12 31 0.98866
2019 1 31 0.92582
2019 2 28 0.95508
2019 3 31 0.99525
2019 4 30 0.99393
2019 5 15 0.95888
>>

Categories

Find more on Dates and Time in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!