且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

R:使用上一行的值更新(受条件限制)

更新时间:2022-10-17 23:15:07

可能有更好的方法,但这是我的想法。这使用 roll = TRUE 参数。想法是首先设置 energy = 0.0 其中前景< 0.27

 字段[prospects< 0.27,energy:= 0.0] 

然后,如果我们从字段,我们可以使用 roll = TRUE 通过与所有组合进行联接,如下所示:

 字段[!is.na(energy)] [CJ(c(a,b),1:3) = field $ prospects] [] 
#玩家时间前景能量
#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

我们必须重置潜在客户,因为 roll 更改它也。






这是一个变体,所以只能在 energy 列:

 字段[!is.na(energy) CJ(c(a,b),1:3),list(energy),
roll = TRUE] [,prospects:= field $ prospects] []






或者使用 na.locf 从包动物园

  = 1,energy:= round(rnorm(2),2)] 
field [prospects& 0.27,energy:= 0.0]
require(zoo)
field [,energy:= na.locf(energy,na.rm = FALSE)]
/ pre>

如果每个组的第一行保证为非NA,这是按照构造工作的。但是如果没有,你也可以按组运行na.locf:

  field [,energy:= na.locf ,na.rm = FALSE),by = player] 


I would like to update the value in a table with values of the previous row, within groups, (and probably stop the updates on a given condition)

Here is an example:

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

Here is the table I have.

> 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

Here is the table I want.

> 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

Thanks in advance

Probably there are better ways, but this is what came to my mind. This makes use of roll=TRUE argument. The idea is to first set energy=0.0 where prospects < 0.27:

field[prospects < 0.27, energy := 0.0]

Then, if we remove the NA values from field, we can use roll=TRUE by doing a join with all combinations as follows:

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

We've to reset prospects because the roll changes it too. You could do it better, but you get the idea.


A variation, so that the roll is performed only on energy column:

field[!is.na(energy)][CJ(c("a", "b"), 1:3), list(energy), 
           roll=TRUE][, prospects := field$prospects][]


Or it may be simpler to use na.locf from package 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)]

which works if the first row of each group is guaranteed to be non-NA, which it is here by construction. But if not, you can run na.locf by group, too :

field[, energy := na.locf(energy, na.rm=FALSE), by=player]