Split a target date interval into seasons and find the percentile of days for each season

1 view (last 30 days)
I have the following seasons:
  • Spring: {01-March , 31-May}
  • Summer: {01-June, 31-August}
  • Autumn: {01-Sep, 30-Nov}
  • Winter: {01-Dec, 28-Feb}
and I also have as a data a reference period, e.g. 01-Jan until 15-Sep (254 days).
What I want is to compute what is the percentile of the days of reference period that belong to each season.
For example, in the present case, we have:
  • Winter: 01-Jan until 28-Feb --> 59 days / 254 days = 23.5%
  • Spring: 01-Mar until 31-May --> 90 days / 254 days = 35%
  • Summer: 01-Jun until 31-Aug --> 90 days / 254 days = 35%
  • Autumn: 01-Sep until 15-Sep --> 15 days /254 days = 6.5%
So the requested values would be {23.5, 35, 35, 6.5}.

Accepted Answer

Scott MacKenzie
Scott MacKenzie on 11 Jul 2021
There might be a way to shorten this, but I think it achieves what you are after. You didn't mention the year, so I set this up as a variable (change, as necessary). This script accommodates leap years. BTW, the number of reference days below is 259. Not sure why this differs from your count of 254.
yr = 2020; % change, as necessary
% reference days of interest
r1= datetime(yr,1,1):datetime(yr,2,eomday(yr,2));
r2= datetime(yr,3,1):datetime(yr,5,31);
r3= datetime(yr,6,1):datetime(yr,8,31);
r4= datetime(yr,9,1):datetime(yr,9,15);
n = length([r1 r2 r3 r4]) % number of reference days
n = 259
percentDays = [length(r1), length(r2), length(r3), length(r4)] /n * 100
percentDays = 1×4
23.1660 35.5212 35.5212 5.7915
  4 Comments

Sign in to comment.

More Answers (2)

Seth Furman
Seth Furman on 14 Jul 2021
To add to Scott's answer, this kind of grouped calculation on timestamped data lends itself well to timetable and groupsummary.
isWinter = @(dt) dt.Month == 12 | dt.Month <= 2;
isSpring = @(dt) 3 <= dt.Month & dt.Month <= 5;
isSummer = @(dt) 6 <= dt.Month & dt.Month <= 8;
isAutumn = @(dt) 9 <= dt.Month & dt.Month <= 11;
referencePeriod = timetable('RowTimes',datetime(2020,1,1):caldays(1):datetime(2020,9,15));
referencePeriod.Season(isWinter(referencePeriod.Time)) = categorical("Winter");
referencePeriod.Season(isSpring(referencePeriod.Time)) = categorical("Spring");
referencePeriod.Season(isSummer(referencePeriod.Time)) = categorical("Summer");
referencePeriod.Season(isAutumn(referencePeriod.Time)) = categorical("Autumn");
counts = groupsummary(referencePeriod,"Season")
counts = 4×2 table
Season GroupCount ______ __________ Winter 60 Spring 92 Summer 92 Autumn 15
counts.Percentages = counts.GroupCount ./ sum(counts.GroupCount)
counts = 4×3 table
Season GroupCount Percentages ______ __________ ___________ Winter 60 0.23166 Spring 92 0.35521 Summer 92 0.35521 Autumn 15 0.057915

Peter Perkins
Peter Perkins on 27 Jul 2021
Another possibility:
>> yr = 2020;
>> edges = datetime(yr,[1 3 6 9 12,12],[1 1 1 1 1 32])
edges =
1×6 datetime array
01-Jan-2020 01-Mar-2020 01-Jun-2020 01-Sep-2020 01-Dec-2020 01-Jan-2021
>> t = datetime(yr,1,1:259)';
>> tf = isbetween(t,edges(1:end-1),edges(2:end),'openright'); % uses implicit expansion
>> tf(:,1) = tf(:,1) + tf(:,end);
>> tf(:,end) = [];
>> 100*sum(tf,1)/length(t)
ans =
23.166 35.521 35.521 5.7915

Community Treasure Hunt

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

Start Hunting!

Translated by