如何用另一个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
相关产品推荐
相关产品推荐

