SOLVED: Summing values together until certain value is reached - then repeat - and plot

35 次查看(过去 30 天)
Let's get right into it:
I have yearly data for water level increase in my water tank. I need to find out that on which days the water level reaches tank capacity (lets say 500 liters), then plotting these days on the same graph as the 'water per day'. When the maximum capacity is reached (= tank is emptied), the "countdown" should then start again, and so on.
Experimenting with cumsum has gotten me nowhere and I have not managed to create a sufficient loop to do this.
% Time of year % Water per day [liters]
'01-Jan-2018 00:00:00' 50.2106332550196
'02-Jan-2018 00:00:00' 69.1231162561486
'03-Jan-2018 00:00:00' 39.2133461192996
'04-Jan-2018 00:00:00' 35.1911633369915
'05-Jan-2018 00:00:00' 70.7909634228800
'06-Jan-2018 00:00:00' 45.2770948623210
'07-Jan-2018 00:00:00' 103.742125124495
'08-Jan-2018 00:00:00' 104.090498552586
'09-Jan-2018 00:00:00' 49.9451044989908
'10-Jan-2018 00:00:00' 9.75987421081660
'11-Jan-2018 00:00:00' 8.65371484802794
'12-Jan-2018 00:00:00' 2.47031260215833
'13-Jan-2018 00:00:00' 28.3093648636441
'14-Jan-2018 00:00:00' 113.381792987146
I've tried scrolling through the forums and stackexchange but no luck so far. I found the following answer to a similar problem, but the thread was 6 years old and I did not get it to work in MATLAB 2019b (with the $ and everything).
df$difference_sum <- c(0, head(cumsum(df$difference), -1))
# get length of 0's (first keep value gives the actual length)
len <- sum(df$difference_sum %/% 500 == 0)
df$keep <- (seq_len(nrow(df))-1) %/% len
df <- transform(df, difference_sum = ave(difference, keep,
FUN=function(x) c(0, head(cumsum(x), -1))))
I also tried to following loop, to no avail.
A= H2O_perday;
sum1=0;
k=1;
s = [];
while sum1 < 500
s =sum1;
sum1=sum1+A(k);
k=k+1;
end
disp(s);
disp(k-1);
Does anyone here have experience with a similar issue that could help me or show me some tips on how to proceed in this?

采纳的回答

dpb
dpb 2020-1-28
OK, a working script...I set the setpoint to 250 so would have more than one condition satisfied for testing...
tt.Level=zeros(height(tt),1);
C = 250;
tt.Level=cumsum(tt.Fill);
i1 = 1;
i2 = find(tt.Level>=C,1);
while i2 <= height(tt)
i1=i2+1;
%tt.Level(i1:end) = tt.Level(i1:end) - tt.Level(i1);
tt.Level(i1:end)=cumsum(tt.Fill(i1:end));
i2=find(cumsum(tt.Fill(i1:end))>=C,1) + i1-1;
if isempty(i2), break, end
end
produced:
>> tt
tt =
14×2 timetable
Time Fill Level
___________ ______ ______
01-Jan-2018 50.21 50.21
02-Jan-2018 69.12 119.33
03-Jan-2018 39.21 158.55
04-Jan-2018 35.19 193.74
05-Jan-2018 70.79 264.53
06-Jan-2018 45.28 45.28
07-Jan-2018 103.74 149.02
08-Jan-2018 104.09 253.11
09-Jan-2018 49.95 49.95
10-Jan-2018 9.76 59.70
11-Jan-2018 8.65 68.36
12-Jan-2018 2.47 70.83
13-Jan-2018 28.31 99.14
14-Jan-2018 113.38 212.52
>>
  1 个评论
Tarmo Tukiainen
Tarmo Tukiainen 2020-1-29
Perfect! It works like a charm also with the hourly data I have stored. Thank you for all your help and I wish you a good rest of the week!

请先登录,再进行评论。

更多回答(1 个)

dpb
dpb 2020-1-24
Not fully coded, but the idea should work to build loop...
t=readtable('tarmo.dat','HeaderLines',1);
t.Var1=strrep(t.Var1,'''',''); % remove extra ' in the date strings
t.Var1=datetime(t.Var1); % convert to date
t=timetable(t.Var3,'rowtimes',t.Var1); % make into time table
t.Properties.VariableNames={'DailyFill (l)'};
C=500; % Capacity level
i1=1;
i2=find(cumsum(t.("DailyFill (l)"))>=C,1); % First location exceed capacity
while i2<=height(t) % iterate
i1=i2+1; % next start
t.Level(i1:end)=t.Level(i1:end)-tt.Level(i1); % reset
t.(Level,i1:end)=cumsum(t.("DailyFill (l)")(i1:end)); % new cumulative flow (fill)
i2=find(cumsum(t.("DailyFill (l)")(i:end)>=C,1)+i1; % First location exceed capacity beginning next
end
WARNING: Air code, only minimally tested for first/second cases sequentially at command line; not in loop. Debugging undoubtedly required!
  10 个评论
Tarmo Tukiainen
Tarmo Tukiainen 2020-1-28
Ah yes that's similar to what I had in mind!
My complete code is the following and the above shown results are with this.
t = TT_bat_KG ;
t.Level=zeros(height(t),1);
C = 500; % Capacity level
t.Level=cumsum(t.("Total[kg/d]")) ;
i1 = 1;
i2 = find(t.Level >= C,1);
while i2 <= height(t)
i1 = i2 + 1;
t.Level(i1:end) = t.Level(i1:end) - t.Level(i1);
t.Level(i1:end)=cumsum(t.("Total[kg/d]")(i1:end));
i2 = find(cumsum(t.("Total[kg/d]")(i1:end))>=C,1) + i1;
end
In my eyes it should indeed restart immediately. I have tried to switch the >= sign into both == and <= signs, but then I get an error regarding indexing (Index exceeds the number of array elements (365) & Error in tabular/dotParenReference, b = b(rowIndiced).
Any idea what might be wrong with the code?
dpb
dpb 2020-1-28
Yeah, there's an "off by one" logic error in the adjustment for the offset from origin in the calculation of i2; use
i2 = find(cumsum(t.("Total[kg/d]")(i1:end))>=C,1) + i1-1;
instead. i2 is from origin of the subset vector which is one-based so the offset is/needs be 0-based.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Data Type Identification 的更多信息

产品


版本

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by