我想更新表中的值,包含组中的上一行的值(并且可能在给定条件下停止更新)
这是一个例子:
set.seed(12345)
field <- data.table(time=1:3, player = letters[1:2], prospects = round(rnorm(6),2))
setkey(field, player, time)
field[time == 1, energy := round(rnorm(2),2)] #initial level - this is what I want to propagate down the table
#let 'prospects < 0.27' be the condition that stops the process, and sets 'energy = 0'
#player defines the groups within which the updates are made
Run Code Online (Sandbox Code Playgroud)
这是我的桌子.
> field
time player prospects energy
1: 1 a 0.81 -0.32
2: 2 a 0.25 NA
3: 3 a 2.05 NA
4: 1 b 1.63 -1.66
5: 2 b 2.20 NA
6: 3 b 0.49 NA
Run Code Online (Sandbox Code Playgroud)
这是我想要的表.
> field
time player prospects energy
1: 1 a 0.81 -0.32
2: 2 a 0.25 0
3: 3 a 2.05 0
4: 1 b 1.63 -1.66
5: 2 b 2.20 -1.66
6: 3 b 0.49 -1.66
Run Code Online (Sandbox Code Playgroud)
提前致谢
可能有更好的方法,但这就是我想到的。这就利用了roll=TRUE
论证。这个想法是首先设置energy=0.0
位置prospects < 0.27
:
field[prospects < 0.27, energy := 0.0]
Run Code Online (Sandbox Code Playgroud)
然后,如果我们从 中删除 NA 值field
,我们可以roll=TRUE
通过对所有组合进行连接来使用,如下所示:
field[!is.na(energy)][CJ(c("a", "b"), 1:3), roll=TRUE][, prospects := field$prospects][]
# player time prospects energy
# 1: a 1 0.81 0.63
# 2: a 2 0.25 0.00
# 3: a 3 2.05 0.00
# 4: b 1 1.63 -0.28
# 5: b 2 2.20 -0.28
# 6: b 3 0.49 -0.28
Run Code Online (Sandbox Code Playgroud)
我们必须重置,prospects
因为roll
它也会改变。你可以做得更好,但你明白了。
一种变体,以便仅在列上执行滚动energy
:
field[!is.na(energy)][CJ(c("a", "b"), 1:3), list(energy),
roll=TRUE][, prospects := field$prospects][]
Run Code Online (Sandbox Code Playgroud)
na.locf
或者从包中使用可能更简单zoo
:
field[time == 1, energy := round(rnorm(2),2)]
field[prospects < 0.27, energy := 0.0]
require(zoo)
field[, energy := na.locf(energy, na.rm=FALSE)]
Run Code Online (Sandbox Code Playgroud)
如果保证每组的第一行是非 NA 的,则该方法有效,这是通过构造实现的。但如果没有,您也可以按组运行 na.locf :
field[, energy := na.locf(energy, na.rm=FALSE), by=player]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1848 次 |
最近记录: |