使用先前行值的滚动函数[R]

7xllpg7q  于 2023-04-09  发布在  其他
关注(0)|答案(1)|浏览(89)

我有一些站点(a,b,c),其中土壤具有一定的最大容量(100,200)。对于每个时间段(数据集中的每行),我计算了含水量的变化(change)。

set.seed(2023)
db <- data.table(ID=c(rep("a",3),rep("b",3),rep("c",3)),
                 capacity=c(rep(100,3),rep(200,6)),
                 prc=round(runif(9,1,100),0),
                 evpt=round(runif(9,1,100),0))

db[prc>=evpt,change:=prc-evpt]
db[prc<evpt,change:=exp(-((evpt-prc)/capacity))]

   ID capacity prc evpt     change
1:  a      100  39   20 19.0000000
2:  a      100  74   35 39.0000000
3:  a      100  67   19 48.0000000
4:  b      200  49   78  0.8650223
5:  b      200  41   70  0.8650223
6:  b      200  94   75 19.0000000
7:  c      200  74   51 23.0000000
8:  c      200  67   71  0.9801987
9:  c      200  77   73  4.0000000

在时间0,站点拥有最大的水capacity。然后,如果prcevpt,则change是添加到先前含量的水,而不超过最大容量。如果prcevpt,则change是先前水含量的乘数,因此减少了含量。

# draft function
new_content <- function(change,capacity,prc,evpt){
  if (prc>evpt) {
    min(change+previous_content,capacity)
    } else {
      previous_content*change
    }
}

然后,我应该为每个站点应用该函数,以获得一个新的列(content),显示含水量的时间变化。如以下在Excel中计算的输出:

> db
   ID capacity prc evpt     change  content
1:  a      100  39   20 19.0000000 100.0000
2:  a      100  74   35 39.0000000 100.0000
3:  a      100  67   19 48.0000000 100.0000
4:  b      200  49   78  0.8650223 173.0045
5:  b      200  41   70  0.8650223 149.6527
6:  b      200  94   75 19.0000000 168.6527
7:  c      200  74   51 23.0000000 200.0000
8:  c      200  67   71  0.9801987 196.0397
9:  c      200  77   73  4.0000000 200.0000

我无法解决的问题是如何定义变量previous_content,即在开始时等于最大容量,然后等于前一行的内容。
我检查了data.table::frollapplyzoo:rollapply的文档,但我甚至不能写一个开始草案。任何帮助?谢谢!

djmepvbi

djmepvbi1#

假设注解中所示的使用Reduce生成的content2结尾处的输入与content相同:

db[, content2 := Reduce(function(x, i) with(.SD[i, ], {
    if (prc > evpt) min(change+x, capacity)
    else x * change
  }), 1:.N, init = capacity[1], acc = TRUE)[-1], by = ID]

db
##    ID capacity prc evpt     change  content content2
## 1:  a      100  39   20 19.0000000 100.0000 100.0000
## 2:  a      100  74   35 39.0000000 100.0000 100.0000
## 3:  a      100  67   19 48.0000000 100.0000 100.0000
## 4:  b      200  49   78  0.8650223 173.0045 173.0045
## 5:  b      200  41   70  0.8650223 149.6527 149.6527
## 6:  b      200  94   75 19.0000000 168.6527 168.6527
## 7:  c      200  74   51 23.0000000 200.0000 200.0000
## 8:  c      200  67   71  0.9801987 196.0397 196.0397
## 9:  c      200  77   73  4.0000000 200.0000 200.0000

在问题的例子中,capacityID内始终是常数,如果change〈= 1,则乘以change,否则相加。如果这些都是真的,通常我们可以简化上面的内容:

db[, content3 := Reduce(function(x, change) 
      if (change > 1) min(change + x, capacity[1]) else x * change, 
      change, init = capacity[1], acc = TRUE)[-1], 
    by = ID]

注意事项

library(data.table)

Lines <-  "ID capacity prc evpt     change  content
a      100  39   20 19.0000000 100.0000
a      100  74   35 39.0000000 100.0000
a      100  67   19 48.0000000 100.0000
b      200  49   78  0.8650223 173.0045
b      200  41   70  0.8650223 149.6527
b      200  94   75 19.0000000 168.6527
c      200  74   51 23.0000000 200.0000
c      200  67   71  0.9801987 196.0397
c      200  77   73  4.0000000 200.0000"
db <- fread(Lines)

相关问题