想象一下R
中的data.table
是这样的:
dtable = data.table(
id = c(1, 1, 1, 2, 2, 2),
time = c(1, 2, 3, 2, 3, 4),
value_a = c(NA, 'Yes', NA, 'No', NA, 'Yes'),
value_b = c('No', 'Yes', NA, NA, NA, NA)
)
cols <- c("value_a", "value_b")
,其计算结果为
id time value_a value_b
1: 1 1 <NA> No
2: 1 2 Yes Yes
3: 1 3 <NA> <NA>
4: 2 2 No <NA>
5: 2 3 <NA> <NA>
6: 2 4 Yes <NA>
对于每个id
和time
,我希望扩展最新的观察值(<NA>
对应于无观察值)。也就是说,我正在寻找一种有效的方法来创建结果表:
id time value_a value_b
1: 1 1 <NA> No
2: 1 2 Yes Yes
3: 1 3 Yes Yes
4: 2 2 No <NA>
5: 2 3 No <NA>
6: 2 4 Yes <NA>
我的数据集非常大,所以效率很重要。
发布于 2018-06-04 23:19:29
这应该会更快。
使用zoo
包中的na.locf
(forward filling ),您可以执行以下操作:
dtable[, c('value_a','value_b') := lapply(.SD, na.locf, na.rm=F), .SDcols = c('value_a','value_b'), .(id)]
print(dtable)
id time value_a value_b
1: 1 1 NA No
2: 1 2 Yes Yes
3: 1 3 Yes Yes
4: 2 2 No NA
5: 2 3 No NA
6: 2 4 Yes NA
发布于 2018-06-04 19:19:47
受@chinsoon12的启发,我想出了以下解决方案
cols <- c("value_a", "value_b")
dtable[, (cols) := lapply(.SD, function(x) {
if (.N > 1) {
na_idx = which(is.na(x))
value_idx = which(!is.na(x))
# determine if there are any non NA values
if (length(value_idx) > 0){
# update all NAs observed after an actual observed observation
if (length(na_idx[na_idx > min(value_idx)]) > 0)
na_idx[na_idx > min(value_idx)] <- sapply(na_idx[na_idx > min(value_idx)], function(i) max(value_idx[value_idx < i]))
# build new index array to use for return
replace_with_idx <- c(na_idx, value_idx)
return(x[replace_with_idx[order(replace_with_idx)]])
} else {
NA # if all NA
}
}
x # if only one observed value
}),
by=id, .SDcols=cols]
https://stackoverflow.com/questions/50676684
复制相似问题