这是令人惊讶的困难,但是我正在尝试按照标题所述进行操作,例如,假设我有一个数据表dat
,并且我正在尝试在新列(从第1行到第1行, 3,当它出现在2nd中时,任何组出现在第二列中。
dat = data.table(A=c(1,2,3,1,4,5,1,2,3),B=c(1,1,1,NA,1,NA,2,NA,2),C=c(1,12,24.2,251,2,1,2,3,-1))
dat[,cumsum:=0]
所以数据看起来像
> dat
A B C
1: 1 1 1.0
2: 2 1 12.0
3: 3 1 24.2
4: 1 NA 251.0
5: 4 1 2.0
6: 5 NA 1.0
7: 1 2 2.0
8: 2 NA 3.0
9: 3 2 -1.0
我希望输出为:
> dat
A B C cumsum
1: 1 1 1.0 1
2: 2 1 12.0 1
3: 3 1 24.2 1
4: 1 NA 251.0 0
5: 4 1 2.0 252
6: 5 NA 1.0 0
7: 1 2 2.0 12
8: 2 NA 3.0 0
9: 3 2 -1.0 15
是否有一种有效的数据表方法可以做到这一点?我可以使用循环来做到这一点,但这会很慢,而且我觉得这必须以更可扩展的方式来实现,但我遇到了麻烦。
答案 0 :(得分:6)
使用非等价自我联接的一种可能方法:
dat[, rn := .I]
dat[!is.na(B), cumsum := dat[.SD, on=.(A=B, rn<=rn), sum(x.C), by=.EACHI]$V1]
输出:
A B C cumsum rn
1: 1 1 1.0 1 1
2: 2 1 12.0 1 2
3: 3 1 24.2 1 3
4: 1 NA 251.0 0 4
5: 4 1 2.0 252 5
6: 5 NA 1.0 0 6
7: 1 2 2.0 12 7
8: 2 NA 3.0 0 8
9: 3 2 -1.0 15 9
数据:
dat = data.table(A=c(1,2,3,1,4,5,1,2,3),B=c(1,1,1,NA,1,NA,2,NA,2),C=c(1,12,24.2,251,2,1,2,3,-1))
dat[,cumsum:=0]
编辑:添加另一种受弗兰克答案启发的方法
dat = data.table(A=c(1,2,3,1,4,5,1,2,3),B=c(1,1,1,NA,1,NA,2,NA,2),C=c(1,12,24.2,251,2,1,2,3,-1))
dat[, rn := .I][, cs := cumsum(C), A]
dat[, cumsum := 0][
!is.na(B), cumsum := dat[.SD, on=.(A=B, rn), allow.cartesian=TRUE, roll=TRUE, x.cs]]
答案 1 :(得分:4)
与@chinsoon的答案相同,但采用滚动连接:
dat[, rn := .I]
mDT = dat[.(setdiff(B, NA)), on=.(A), .(rn, v = cumsum(C)), by=.EACHI]
dat[, cumsum := 0]
dat[!is.na(B), cumsum := mDT[.SD, on=.(A=B, rn), roll=TRUE, x.v]]
A B C cumsum rn
1: 1 1 1.0 1 1
2: 2 1 12.0 1 2
3: 3 1 24.2 1 3
4: 1 NA 251.0 0 4
5: 4 1 2.0 252 5
6: 5 NA 1.0 0 6
7: 1 2 2.0 12 7
8: 2 NA 3.0 0 8
9: 3 2 -1.0 15 9
对于B
的每个值,mDT
具有A
的对应行,并具有行号和总和。我们通过滚动到最近的行号来查找该累加的最新值。
这是@chinsoon建议的另一种滚动联接方法:
dat[, rn := .I]
dat[, cs := cumsum(C), by=A]
dat[, cumsum := 0]
dat[ !is.na(B), cumsum := dat[.SD, on=.(A=B, rn), allow.cartesian=TRUE, roll=TRUE, x.cs]]
答案 2 :(得分:2)
不是data.table
解决方案,而是使用dplyr
的一种方法是
library(dplyr)
dat %>%
mutate(row = row_number(),
cumsum = purrr::map2_dbl(B, row, ~sum(C[A == .x & row <= .y], na.rm = TRUE))) %>%
select(-row)
# A B C cumsum
#1 1 1 1.0 1
#2 2 1 12.0 1
#3 3 1 24.2 1
#4 1 NA 251.0 0
#5 4 1 2.0 252
#6 5 NA 1.0 0
#7 1 2 2.0 12
#8 2 NA 3.0 0
#9 3 2 -1.0 15
不确定仅针对sum
的非NA值来计算B
是否有效?
dat %>%
mutate(row = row_number(),
cumsum = ifelse(is.na(B), 0,
purrr::map2_dbl(B, row, ~sum(C[A == .x & row <= .y], na.rm = TRUE)))) %>%
select(-row)