【问题标题】:Refer to previous row in data.table in R, with a condition参考 R 中 data.table 中的上一行,带有条件
【发布时间】:2016-02-27 09:42:27
【问题描述】:

我对这些数据有一个新问题。因为我的完整数据有这样的形式

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  

现在,我想创建一个新列,它计算壁橱上一行的A与B/C的倍数,只要B不为0。例如,在第2行,我可以计算D=2*(1/2)。但是,在第 4 行,它必须是 4*(2/3),不能是 4*(0/1)。 我用

a[, D:= {i1 <- (NA^!B)
list( A*shift(na.locf(i1*B))/shift(na.locf(i1*C)))},by=d]

正如 Akrun 昨天推荐的那样。按组计算时它不起作用。结果是这样的

    A B C d        D
# 1:  1 1 2 1       NA
# 2:  2 2 3 1 1.000000
# 3:  3 0 1 1 2.000000
# 4:  4 2 4 1 2.666667
# 5:  5 0 5 1 2.500000
# 6:  6 0 3 2       NA
# 7:  7 3 6 2 3.500000
# 8:  8 4 7 2 4.571429
# 9:  9 0 2 2 5.142857
# 10: 10 2 2 2       NA

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

【问题讨论】:

  • D 的第一个元素的输出是什么?
  • D 的第一个元素的输出将是 NA

标签: r data.table


【解决方案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]])}]

或者我们可以使其紧凑。我们得到一个逻辑向量 (!B),它检查 'B' 中的 '0' 元素,将其转换为 1 和 NA 的向量 (NA^),与列 'B' 和 'C' 相乘,这样1 被这些列中的相应元素替换,而 NA 保持不变。做na.locf(和以前一样),shift,然后做乘法/除法。

a[, D:= {i1 <- (NA^!B)
   list( A*shift(na.locf(i1*B))/shift(na.locf(i1*C)))}]

或者不是两次调用shift/na.locf

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

【讨论】:

  • 谢谢。你真的解决了我的问题。它也很紧凑。
  • 嗨,@akrun,你能看一下吗?
  • @ThanhQuang 你可能需要...na.locf(i1*B), na.rm=FALSE)/shift(na.locf(i1*C, na.rm=FALSE)...
  • 谢谢。现在一切都解决了。非常感谢你
【解决方案2】:

这可以通过滚动连接来完成:

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

【讨论】:

    猜你喜欢
    • 2015-06-19
    • 2015-10-06
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 2020-09-12
    相关资源
    最近更新 更多