问题描述
library(data.table)
set.seed(123)
dt = data.table( grp=round(runif(10)),val=c(runif(4),NA,runif(4),NA) )
dt
输出为:
grp val
1: 0 0.95683335
2: 1 0.45333416
3: 0 0.67757064
4: 1 0.57263340
5: 1 NA
6: 0 0.10292468
7: 1 0.89982497
8: 1 0.24608773
9: 1 0.04205953
10: 0 NA
我想用之前的非 NA 值 val
填充 val
。
SO 问题“用最新的非 NA 值替换 NA”有 an amazing SO answer,我不完全理解。尽管如此,我还是尝试了:
dt[,val2 := val[1],.(grp,cumsum(!is.na(val))) ]
dt
输出为:
grp val val2
1: 0 0.95683335 0.95683335
2: 1 0.45333416 0.45333416
3: 0 0.67757064 0.67757064
4: 1 0.57263340 0.57263340
5: 1 NA 0.57263340
6: 0 0.10292468 0.10292468
7: 1 0.89982497 0.89982497
8: 1 0.24608773 0.24608773
9: 1 0.04205953 0.04205953
10: 0 NA NA
这几乎有效(它正确填充了第 5 行)。为什么 dt
的第 10 行的 NA
值仍然是 val2
而不是 0.10292468
(之前 grp == 0
的非 NA 值)?>
解决方法
nafill
中有一个 data.table
library(data.table)
dt[,val2 := nafill(val,type = 'locf')]
-输出
dt
# grp val val2
# 1: 0 0.95683335 0.95683335
# 2: 1 0.45333416 0.45333416
# 3: 0 0.67757064 0.67757064
# 4: 1 0.57263340 0.57263340
# 5: 1 NA 0.57263340
# 6: 0 0.10292468 0.10292468
# 7: 1 0.89982497 0.89982497
# 8: 1 0.24608773 0.24608773
# 9: 1 0.04205953 0.04205953
#10: 0 NA 0.04205953
在 OP 的输出中它是 NA
的原因是基于分组
dt[,cumsum(!is.na(val))]
#[1] 1 2 3 4 4 5 6 7 8 8
最后两个元素被分组为 8,其中 'grp' 最后一个元素是 0,所以只有一个元素匹配,如果我们使用 val[1]
which NA
,我们得到了NA
如果我们用 .GRP
参数检查 by
会更清楚
dt[,.GRP,by = .(grp1 = cumsum(!is.na(val)),grp)]
# grp1 grp GRP
#1: 1 0 1
#2: 2 1 2
#3: 3 0 3
#4: 4 1 4
#5: 5 0 5
#6: 6 1 6
#7: 7 1 7
#8: 8 1 8
#9: 8 0 9 # -> only a single element for group 9
因此,val[1]
返回 NA
元素
但是,如果我们对 'grp' 执行 order
然后使用 cumsum
创建新组,相邻元素是不同的,因此每组有多个元素
奇怪。我只是注意到我提到的 SO 答案首先由 dt
订购了 grp
。我试过了,它奏效了。
dt = data.table( grp=round(runif(10)),val=c(runif(4),NA,runif(4),NA) )
dt = dt[ order(grp),] ## seems to be critical step
dt[,val2 := val[1],.(grp,cumsum(!is.na(val))) ]
dt
输出为:
grp val val2
1: 0 0.95683335 0.95683335
2: 0 0.67757064 0.67757064
3: 0 0.10292468 0.10292468
4: 0 NA 0.10292468
5: 1 0.45333416 0.45333416
6: 1 0.57263340 0.57263340
7: 1 NA 0.57263340
8: 1 0.89982497 0.89982497
9: 1 0.24608773 0.24608773
10: 1 0.04205953 0.04205953