我对这些数据有新的问题。因为我的完整数据有这样的形式
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的前一行的A倍数值。例如,在第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
有谁知道这里有什么问题?错误是较长的对象长度不是较短对象长度的倍数。
答案 0 :(得分:3)
我们可以替换&#39; B&#39; C&#39; C&#39;对应于&#39; 0&#39; 0 &#39; B&#39;作为NA。使用na.locf
中的zoo
将这些NA值替换为之前的非NA元素,shift
元素(默认情况下,它给出的lag
为1),除以修改后的列&#39; B&#39;用&#39; C&#39;然后乘以&#39; A&#39;。将输出分配(:=
)到新列&#39; D&#39;。
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
)来检查&#39; 0&#39; &#39; B&#39;中的元素,将其转换为1s和NA(NA^
)的向量,乘以列&#39; B&#39;和&#39; C&#39;因此,1s被那些列中的相应元素替换,而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]
答案 1 :(得分:3)
这可以通过滚动连接来完成:
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