参考R中data.table中的上一行,带有条件

参考R中data.table中的上一行,带有条件,r,data.table,R,Data.table,我对这些数据有一个新的问题。因为我的全部数据都是这样的 a=data.table(A=c(1:10),B=c(1,2,0,2,0,0,3,4,0,2),C=c(2,3,1,4,5,3,6,7,2,2),D=c(1,1,1,1,1,2,2,2,2,2)) # A B C D # 1: 1 1 2 1 # 2: 2 2 3 1 # 3: 3 0 1 1 # 4: 4 2 4 1 # 5: 5 0 5 1 # 6: 6 0 3 2 # 7: 7

我对这些数据有一个新的问题。因为我的全部数据都是这样的

a=data.table(A=c(1:10),B=c(1,2,0,2,0,0,3,4,0,2),C=c(2,3,1,4,5,3,6,7,2,2),D=c(1,1,1,1,1,2,2,2,2,2)) 


#     A B C D  
# 1:  1 1 2 1  
# 2:  2 2 3 1  
# 3:  3 0 1 1  
# 4:  4 2 4 1  
# 5:  5 0 5 1  
# 6:  6 0 3 2  
# 7:  7 3 6 2  
# 8:  8 4 7 2  
# 9:  9 0 2 2  
#10: 10 2 2 2  
现在,我想创建一个新列,只要B不是0,它就可以计算上一行B/C的倍数。例如,在第2行中,我可以计算D=2*(1/2)。但是,在第4行中,它必须是4*(2/3),不能是4*(0/1)。 我用


有人知道这里有什么问题吗?错误是较长的对象长度不是较短对象长度的倍数。

我们可以将“B”、“C”中与“B”中的“0”值对应的元素替换为NA。使用
zoo
中的
na.locf
将这些na值替换为以前的非na元素,
shift
元素(默认情况下,它给出的
lag
为1),将修改后的列“B”除以“C”,然后乘以“a”。将(
:=
)输出分配给新列“D”

 library(zoo)
 a[B==0, c('B', 'C'):=list(NA, NA)]
 a[, c('B', 'C'):= na.locf(.SD), .SDcols=B:C]
 a[,  D:= {tmp <- shift(.SD[, 2:3, with=FALSE])
           A*(tmp[[1]]/tmp[[2]])}]
或者不调用两次
shift/na.locf

a[,  D:= {i1 <- (NA^!B)
      tmp <- shift(na.locf(i1*.SD))
      a[['A']]*(tmp[[1]]/tmp[[2]])}, .SDcols=B:C]

a[,D:={i1这可以通过滚动连接完成:

a[, row := .I]
a[, B/C, by=row][V1 != 0][a, A*shift(V1), on="row", roll=TRUE]
# [1]       NA 1.000000 2.000000 2.666667 2.500000 3.000000 3.500000 4.000000
# [9] 5.142857 5.714286

D的第一个元素的输出是什么?D的第一个元素的输出是NAThanks。你真的解决了我的问题。它也很紧凑。嗨,@akrun,你能看一下吗?@ThanhQuang你可能需要
…na.locf(i1*B),na.rm=FALSE)/shift(na.locf(i1*C,na.rm=FALSE)…
谢谢。现在一切都解决了。非常感谢您
a[, D:= {i1 <- (NA^!B)
   list( A*shift(na.locf(i1*B))/shift(na.locf(i1*C)))}]
a[,  D:= {i1 <- (NA^!B)
      tmp <- shift(na.locf(i1*.SD))
      a[['A']]*(tmp[[1]]/tmp[[2]])}, .SDcols=B:C]
a[, row := .I]
a[, B/C, by=row][V1 != 0][a, A*shift(V1), on="row", roll=TRUE]
# [1]       NA 1.000000 2.000000 2.666667 2.500000 3.000000 3.500000 4.000000
# [9] 5.142857 5.714286