Daywise differences in array

1 view (last 30 days)
Poulomi
Poulomi on 8 Oct 2024
Edited: dpb on 12 Oct 2024
Hello
I have the following time series
1982 5 1 3 25
1982 5 1 6 30
1982 5 1 12 35
1982 5 1 18 40
1982 5 2 0 45
1982 5 2 3 45
1982 5 2 6 50
1982 5 2 12 55
1982 5 2 18 55
1982 5 3 0 60
1982 5 3 3 65
1982 5 3 6 80
1982 5 3 12 90
1982 5 3 18 105
1982 5 4 0 115
1982 5 4 3 115
1982 5 4 6 115
1982 5 4 12 115
1982 5 4 18 115
1982 5 5 3 30
The first four columns show year, month, day and hour and the last column shows the 3-hourly rainfall. I wish to find out if the rainfall value at each 3-hourly time series is more than 30 mm within the next 24 hours. For example, the difference in rainfall value of 1982/5/1 at 3 hrs - 1982/5/2 at 3hrs should be greater than 30 mm. This I need to search for the entire series and locate the rows where the difference in rainfall values are more than 30 mm from its previous 24 hrour values. I am trying with caldays(1) but getting stuck for the end rows. Also, my approach ionvolves for loop, which is not efficient. Pls. help!

Accepted Answer

dpb
dpb on 8 Oct 2024
Edited: dpb on 9 Oct 2024
R=[1982 5 1 3 25
1982 5 1 6 30
1982 5 1 12 35
1982 5 1 18 40
1982 5 2 0 45
1982 5 2 3 45
1982 5 2 6 50
1982 5 2 12 55
1982 5 2 18 55
1982 5 3 0 60
1982 5 3 3 65
1982 5 3 6 80
1982 5 3 12 90
1982 5 3 18 105
1982 5 4 0 115
1982 5 4 3 115
1982 5 4 6 115
1982 5 4 12 115
1982 5 4 18 115
1982 5 5 3 30];
ttR=timetable(datetime(R(:,1:3))+hours(R(:,4)),R(:,5),'VariableNames',{'Rainfall'})
ttR = 20x1 timetable
Time Rainfall ____________________ ________ 01-May-1982 03:00:00 25 01-May-1982 06:00:00 30 01-May-1982 12:00:00 35 01-May-1982 18:00:00 40 02-May-1982 00:00:00 45 02-May-1982 03:00:00 45 02-May-1982 06:00:00 50 02-May-1982 12:00:00 55 02-May-1982 18:00:00 55 03-May-1982 00:00:00 60 03-May-1982 03:00:00 65 03-May-1982 06:00:00 80 03-May-1982 12:00:00 90 03-May-1982 18:00:00 105 04-May-1982 00:00:00 115 04-May-1982 03:00:00 115
LastTime=ttR.Time(end);
t=[]; r=[];
for i=1:height(ttR)
nextDay=ttR.Time(i)+caldays(1);
%[ttR.Time(i) nextDay LastTime]
if nextDay>LastTime, break, end
% account for not accumulating globally as initially thought, Umar's solution
inDay=timerange(ttR.Time(i),nextDay); % indexing expression for 24hr period
%dRF=ttR.Rainfall(nextDay)-ttR.Rainfall(i); % amount difference at now+24hr
dRF=max(ttR.Rainfall(inDay))-ttR.Rainfall(i); % amount difference in 24hr accounting for rollover
%[ttR.Rainfall(i) ttR.Rainfall(nextDay) dRF];
if dRF>30
t=[t;ttR.Time(i)];
r=[r;dRF];
end
end
ttDRF=timetable(t,r,'VariableNames',{'24hr Rainfall'});
ttDRF.Properties.DimensionNames(1)={'Begin Date'};
ttDRF
ttDRF = 4x1 timetable
Begin Date 24hr Rainfall ____________________ _____________ 02-May-1982 18:00:00 35 03-May-1982 00:00:00 45 03-May-1982 03:00:00 50 03-May-1982 06:00:00 35
I couldn't think of a really clever way to use indexting but I doubt this will be too bad unless your data file is really huge....although I did use dynamic reallocation here rather than allocating space for the temporaries.
  11 Comments
dpb
dpb on 10 Oct 2024
"it should be nanmin(ttR.Rainfall(inDay)) as we are looking whether there is an increase of > 30, with max, we may discard a few events."
No, the min() won't find any events; the max() is returning the largest amount in the day in question; the delta computed is then the difference between it and the starting amount of the current 24hr period. The min will return the starting value for almost every 24hr period; only those in which the accumulator been reset will it find another value, and then the computed difference will turn out to be negative.
max() silently discards NaN anyway, so the nanmin, nanmax functions aren't required...
max([10;20;nan])
ans = 20
The potential issue about the reset period is still the one outlined above in the (probably rare) event that the second set of data produce a larger accumulated total than a first set within the 24 hr period after a reset.
One could check for that by finding the locations in the overall at which the sequential diff() of the rainfall is <0 and the checking if any of those dates are within the 24hr band after any of the returned exceedances.
dpb
dpb on 12 Oct 2024
Edited: dpb on 12 Oct 2024
"The potential issue about the reset period..."
Probably the cleanest solution is to add a little more logic...
...
inDay=timerange(ttR.Time(i),nextDay); % indexing expression for 24hr period
rfDay=ttR.Rainfall(inDay); % the accmulations in the 24hr
ixReset=find(diff(rfDay)<0);
if isempty(ixReset) % no reset in this period
dRF=rfdDay(end)-ttR.Rainfall(i); % amount difference in 24hr
else % there is a reset in this period
dRF=rfDay(ixReset)-ttR.Rainfall(i); % amount difference before reset
end
...
The above does the comparison to the period before the reset; the question is then one of a definition of what event(s) are actually wanted --the maximum total in the 24hr period would also include the amout after the reset, if any, in which case one would need the total of the two maxima in the period.
That would be more like
...
ixReset=find(diff(rfDay)<0);
if isempty(ixReset)
dRF=rfdDay(end)-ttR.Rainfall(i);
else
dRF=rfDay(ixReset)-ttR.Rainfall(i)+rfdDay(end); % amount before and after reset
end
...

Sign in to comment.

More Answers (0)

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!