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

huangapple go评论93阅读模式
英文:

rolling function using previous row values [R]

问题

我明白你的需求,你需要翻译代码和相关注释,但不需要翻译其他部分。以下是代码和注释的中文翻译:

  1. # 我有一些地点(`a,b,c`),土壤具有一定的最大容量(`100,200`)。对于每个时间段(数据集中的每一行),我已经计算了水含量的变化(`change`)。
  2. # 设置随机种子
  3. set.seed(2023)
  4. db <- data.table(ID=c(rep("a",3),rep("b",3),rep("c",3)),
  5. capacity=c(rep(100,3),rep(200,6)),
  6. prc=round(runif(9,1,100),0),
  7. evpt=round(runif(9,1,100),0))
  8. # 计算水含量的变化
  9. db[prc>=evpt, change := prc - evpt]
  10. db[prc<evpt, change := exp(-((evpt - prc) / capacity))]
  11. # 在时间0时,地点存储最大的`capacity`水量。然后,如果`prc` > `evpt`,`change`是添加到先前含量的水,但不超过最大容量。如果`prc` < `evpt`,`change`是先前水含量的乘数,从而减少含量。
  12. # 草稿函数
  13. new_content <- function(change, capacity, prc, evpt) {
  14. if (prc > evpt) {
  15. min(change + previous_content, capacity)
  16. } else {
  17. previous_content * change
  18. }
  19. }
  20. # 然后,我应该应用该函数到每个地点,以获得一个新列(`content`),显示水含量的时间变化。如下面在Excel中计算的输出:
  21. # 输出
  22. # > db
  23. # ID capacity prc evpt change content
  24. # 1: a 100 39 20 19.0000000 100.0000
  25. # 2: a 100 74 35 39.0000000 100.0000
  26. # 3: a 100 67 19 48.0000000 100.0000
  27. # 4: b 200 49 78 0.8650223 173.0045
  28. # 5: b 200 41 70 0.8650223 149.6527
  29. # 6: b 200 94 75 19.0000000 168.6527
  30. # 7: c 200 74 51 23.0000000 200.0000
  31. # 8: c 200 67 71 0.9801987 196.0397
  32. # 9: c 200 77 73 4.0000000 200.0000
  33. # 我无法解决的问题是如何定义变量`previous_content`,即一开始等于最大容量,然后等于前一行的内容。
  34. # 我查阅了`data.table::frollapply`和`zoo:rollapply`的文档,但甚至无法为此起草一个初步的草稿。有什么帮助吗?谢谢!

希望这能满足你的需求。如果你有其他问题,请随时提出。

英文:

I have some sites (a,b,c) where the soil has a certain maximum capacity (100,200). For each period of time (every row in my dataset), I have calculated the change in water content (change).

  1. set.seed(2023)
  2. db &lt;- data.table(ID=c(rep(&quot;a&quot;,3),rep(&quot;b&quot;,3),rep(&quot;c&quot;,3)),
  3. capacity=c(rep(100,3),rep(200,6)),
  4. prc=round(runif(9,1,100),0),
  5. evpt=round(runif(9,1,100),0))
  6. db[prc&gt;=evpt,change:=prc-evpt]
  7. db[prc&lt;evpt,change:=exp(-((evpt-prc)/capacity))]
  8. ID capacity prc evpt change
  9. 1: a 100 39 20 19.0000000
  10. 2: a 100 74 35 39.0000000
  11. 3: a 100 67 19 48.0000000
  12. 4: b 200 49 78 0.8650223
  13. 5: b 200 41 70 0.8650223
  14. 6: b 200 94 75 19.0000000
  15. 7: c 200 74 51 23.0000000
  16. 8: c 200 67 71 0.9801987
  17. 9: c 200 77 73 4.0000000

At time 0 the site hold the maximum capacity of water. Then, if prc >evpt, change is the water added to the previous content, without exceeding the maximum capacity. If prc < evpt, change is a multiplier of the previous water content, thus reducing the content.

  1. # draft function
  2. new_content &lt;- function(change,capacity,prc,evpt){
  3. if (prc&gt;evpt) {
  4. min(change+previous_content,capacity)
  5. } else {
  6. previous_content*change
  7. }
  8. }

Then I should apply the function for each site to get a new column (content) showing the temporal variation of water content. As in the following output calculated in Excel:

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

The problem I cannot solve is how to define the variable previous_content, i.e. at the beginning equal to the maximum capacity and then to the content of the previous row.

I checked the documentation of both data.table::frollapply and zoo:rollapply but I was not able even to write a starting draft for that. Any help? Thanks!

答案1

得分: 1

Assuming the input shown in the Note at the end content2 generated using Reduce is the same as content:

  1. db[, content2 := Reduce(function(x, i) with(.SD[i, ], {
  2. if (prc &gt; evpt) min(change+x, capacity)
  3. else x * change
  4. }), 1:.N, init = capacity[1], acc = TRUE)[-1], by = ID]
  5. db
  6. ## ID capacity prc evpt change content content2
  7. ## 1: a 100 39 20 19.0000000 100.0000 100.0000
  8. ## 2: a 100 74 35 39.0000000 100.0000 100.0000
  9. ## 3: a 100 67 19 48.0000000 100.0000 100.0000
  10. ## 4: b 200 49 78 0.8650223 173.0045 173.0045
  11. ## 5: b 200 41 70 0.8650223 149.6527 149.6527
  12. ## 6: b 200 94 75 19.0000000 168.6527 168.6527
  13. ## 7: c 200 74 51 23.0000000 200.0000 200.0000
  14. ## 8: c 200 67 71 0.9801987 196.0397 196.0397
  15. ## 9: c 200 77 73 4.0000000 200.0000 200.0000

In the example in the question capacity is always constant within ID, and change is multiplied if it is <= 1 and added otherwise. If those are true generally, we can simplify the above:

  1. db[, content3 := Reduce(function(x, change)
  2. if (change &gt; 1) min(change + x, capacity[1]) else x * change,
  3. change, init = capacity[1], acc = TRUE)[-1],
  4. by = ID]

Note

  1. library(data.table)
  2. Lines &lt;- "ID capacity prc evpt change content
  3. a 100 39 20 19.0000000 100.0000
  4. a 100 74 35 39.0000000 100.0000
  5. a 100 67 19 48.0000000 100.0000
  6. b 200 49 78 0.8650223 173.0045
  7. b 200 41 70 0.8650223 149.6527
  8. b 200 94 75 19.0000000 168.6527
  9. c 200 74 51 23.0000000 200.0000
  10. c 200 67 71 0.9801987 196.0397
  11. c 200 77 73 4.0000000 200.0000"
  12. db &lt;- fread(Lines)
英文:

Assuming the input shown in the Note at the end content2 generated using Reduce is the same as content:

  1. db[, content2 := Reduce(function(x, i) with(.SD[i, ], {
  2. if (prc &gt; evpt) min(change+x, capacity)
  3. else x * change
  4. }), 1:.N, init = capacity[1], acc = TRUE)[-1], by = ID]
  5. db
  6. ## ID capacity prc evpt change content content2
  7. ## 1: a 100 39 20 19.0000000 100.0000 100.0000
  8. ## 2: a 100 74 35 39.0000000 100.0000 100.0000
  9. ## 3: a 100 67 19 48.0000000 100.0000 100.0000
  10. ## 4: b 200 49 78 0.8650223 173.0045 173.0045
  11. ## 5: b 200 41 70 0.8650223 149.6527 149.6527
  12. ## 6: b 200 94 75 19.0000000 168.6527 168.6527
  13. ## 7: c 200 74 51 23.0000000 200.0000 200.0000
  14. ## 8: c 200 67 71 0.9801987 196.0397 196.0397
  15. ## 9: c 200 77 73 4.0000000 200.0000 200.0000

In the example in the question capacity is always constant within ID and change is multiplied if it is <= 1 and added otherwise. If those are true generally we can simplify the above:

  1. db[, content3 := Reduce(function(x, change)
  2. if (change &gt; 1) min(change + x, capacity[1]) else x * change,
  3. change, init = capacity[1], acc = TRUE)[-1],
  4. by = ID]

Note

  1. library(data.table)
  2. Lines &lt;- &quot;ID capacity prc evpt change content
  3. a 100 39 20 19.0000000 100.0000
  4. a 100 74 35 39.0000000 100.0000
  5. a 100 67 19 48.0000000 100.0000
  6. b 200 49 78 0.8650223 173.0045
  7. b 200 41 70 0.8650223 149.6527
  8. b 200 94 75 19.0000000 168.6527
  9. c 200 74 51 23.0000000 200.0000
  10. c 200 67 71 0.9801987 196.0397
  11. c 200 77 73 4.0000000 200.0000&quot;
  12. db &lt;- fread(Lines)

huangapple
  • 本文由 发表于 2023年4月6日 19:45:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/75949148.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定