You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用另一个data.table的值批量替换目标表中的NA值

批量替换data.table中的NA值

我有两个data.table,其中一个包含若干NA值,需要用另一个data.table对应行列位置的值替换这些NA。目前我可以逐列完成该操作,但想了解是否存在一次性处理所有列的方法。

可复现代码示例

x <- data.table(
  a = runif(10),
  b = runif(10)
)

x[3, a := NA]
x[7, a := NA]
x[5, b := NA]

y <- data.table(
  a = runif(10)*100,
  b = runif(10)*100
)

# 逐列处理可行,但需要逐个列操作
x[is.na(a), a := y[is.na(x$a), a]]
x[is.na(b), b := y[is.na(x$b), b]]


# 循环处理可行,但不确定是否为最优方案
for (i in seq_along(x)) {
  x[[i]] <- ifelse(is.na(x[[i]]), y[[i]], x[[i]])
}

基准测试结果

针对评论区给出的解决方案,进行了基准测试,代码及结果如下:

library(data.table)
library(microbenchmark)

x <- data.table(
  a = runif(10),
  b = runif(10)
)

x[3, a := NA]
x[7, a := NA]
x[5, b := NA]

y <- data.table(
  a = runif(10)*100,
  b = runif(10)*100
)

# 扩大数据量以测试性能
x <- x[rep(1:10,1e4), rep(1:2,50), with=FALSE]
y <- y[rep(1:10,1e4), rep(1:2,50), with=FALSE]

z <- copy(x)

bm <- microbenchmark(
  'latemail方案' = as.data.table(Map(fcoalesce, x, y)),
  'adriano方案' = y * is.na(x) + x[ , lapply(.SD, \(i) ifelse(is.na(i), 0, i))],
  '循环赋值' = {
    for (i in seq_along(x)) {
      z[[i]] <- ifelse(is.na(x[[i]]), y[[i]], x[[i]])
    }
  },
  'set循环' = {
    for(col in seq_along(z)) {
      sel <- which(is.na(x[[col]]))
      set(z, i = sel, j = col, value = y[[col]][sel])
    }
    
  }
)

bm
#> Unit: milliseconds
#>         expr       min        lq      mean    median        uq       max neval
#>  latemail方案  21.18020  23.42095  31.46701  25.58454  36.78618  68.43255   100
#>   adriano方案 518.86065 625.29776 651.63715 646.92010 676.09935 893.32570   100
#>        循环赋值 126.26689 135.11014 144.93929 139.88824 150.09446 184.89310   100
#>       set循环  32.82947  34.51500  39.49935  35.76292  39.03663 104.21157   100

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 11:57:47