由于每个计算依赖于上一次计算的结果,并且它们可能并不总是与简单的累积数学计算(例如,cumsum
)一致,因此我们可以使用Reduce
来获得所需的结果.
# initial conditions
df[1,c("outflow", "storage", "stat")] <- 0
# update each row iteratively
Reduce(function(dat, i) {
dat$outflow[i] = dat$inflow[i-1]/2 + dat$stat[i-1] + dat$storage[i-1]
dat$storage[i] = dat$inflow[i] - dat$outflow[i] + dat$stat[i-1]
dat$stat[i] = dat$inflow[i-1] + dat$stat[i-1] - dat$storage[i-1]
dat
}, 2:nrow(df), init = df)
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 9.0 -0.5 9.0
# 5 5 3 10.5 1.5 13.5
# 6 6 5 16.5 2.0 15.0
# 7 7 6 19.5 1.5 18.0
# 8 8 7 22.5 2.5 22.5
# 9 9 8 28.5 2.0 27.0
# 10 10 9 33.0 3.0 33.0
Reduce
的流程是迭代2:nrow(df)
中的每一个,并使用该数字作为第二个参数调用函数(i
);内部函数的第一个参数是前一次函数调用的结果,在第一次调用时,该函数被init
实例化为df
.(如果我们没有提供init=
,那么内部函数的两个参数应该是2:nrow(df)
中的前两个值,即2
和3
,这不是我们需要的.)
将accumulate=TRUE
添加到调用中可能会提供信息(如果您想了解Reduce
在做什么),它会在每次调用内部函数后显示数据(dat
)的值:
df[1,c("outflow", "storage", "stat")] <- 0
Reduce(function(dat, i) {
dat$outflow[i] = dat$inflow[i-1]/2 + dat$stat[i-1] + dat$storage[i-1]
dat$storage[i] = dat$inflow[i] - dat$outflow[i] + dat$stat[i-1]
dat$stat[i] = dat$inflow[i-1] + dat$stat[i-1] - dat$storage[i-1]
dat
}, seq_len(nrow(df))[-1], init = df, accumulate = TRUE)
# [[1]]
# elevation inflow outflow storage stat
# 1 1 3 0 0 0
# 2 2 4 NA NA NA
# 3 3 6 NA NA NA
# 4 4 4 NA NA NA
# 5 5 3 NA NA NA
# 6 6 5 NA NA NA
# 7 7 6 NA NA NA
# 8 8 7 NA NA NA
# 9 9 8 NA NA NA
# 10 10 9 NA NA NA
# [[2]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0
# 2 2 4 1.5 2.5 3
# 3 3 6 NA NA NA
# 4 4 4 NA NA NA
# 5 5 3 NA NA NA
# 6 6 5 NA NA NA
# 7 7 6 NA NA NA
# 8 8 7 NA NA NA
# 9 9 8 NA NA NA
# 10 10 9 NA NA NA
# [[3]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 NA NA NA
# 5 5 3 NA NA NA
# 6 6 5 NA NA NA
# 7 7 6 NA NA NA
# 8 8 7 NA NA NA
# 9 9 8 NA NA NA
# 10 10 9 NA NA NA
# [[4]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 9.0 -0.5 9.0
# 5 5 3 NA NA NA
# 6 6 5 NA NA NA
# 7 7 6 NA NA NA
# 8 8 7 NA NA NA
# 9 9 8 NA NA NA
# 10 10 9 NA NA NA
# [[5]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 9.0 -0.5 9.0
# 5 5 3 10.5 1.5 13.5
# 6 6 5 NA NA NA
# 7 7 6 NA NA NA
# 8 8 7 NA NA NA
# 9 9 8 NA NA NA
# 10 10 9 NA NA NA
# [[6]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 9.0 -0.5 9.0
# 5 5 3 10.5 1.5 13.5
# 6 6 5 16.5 2.0 15.0
# 7 7 6 NA NA NA
# 8 8 7 NA NA NA
# 9 9 8 NA NA NA
# 10 10 9 NA NA NA
# [[7]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 9.0 -0.5 9.0
# 5 5 3 10.5 1.5 13.5
# 6 6 5 16.5 2.0 15.0
# 7 7 6 19.5 1.5 18.0
# 8 8 7 NA NA NA
# 9 9 8 NA NA NA
# 10 10 9 NA NA NA
# [[8]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 9.0 -0.5 9.0
# 5 5 3 10.5 1.5 13.5
# 6 6 5 16.5 2.0 15.0
# 7 7 6 19.5 1.5 18.0
# 8 8 7 22.5 2.5 22.5
# 9 9 8 NA NA NA
# 10 10 9 NA NA NA
# [[9]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 9.0 -0.5 9.0
# 5 5 3 10.5 1.5 13.5
# 6 6 5 16.5 2.0 15.0
# 7 7 6 19.5 1.5 18.0
# 8 8 7 22.5 2.5 22.5
# 9 9 8 28.5 2.0 27.0
# 10 10 9 NA NA NA
# [[10]]
# elevation inflow outflow storage stat
# 1 1 3 0.0 0.0 0.0
# 2 2 4 1.5 2.5 3.0
# 3 3 6 7.5 1.5 4.5
# 4 4 4 9.0 -0.5 9.0
# 5 5 3 10.5 1.5 13.5
# 6 6 5 16.5 2.0 15.0
# 7 7 6 19.5 1.5 18.0
# 8 8 7 22.5 2.5 22.5
# 9 9 8 28.5 2.0 27.0
# 10 10 9 33.0 3.0 33.0