使用每行avg与stdev生成正态随机数替换data.table中NA值求助
解决用行级均值和标准差填充NA的问题
你的核心需求是用每行自己的avg和stdev生成正态分布随机数,替换该行的NA值。之前的代码没达到预期,主要问题在于按列循环时,你只生成了单个随机数来替换整列的NA,没有对应到每行的参数,而且这种循环方式也没有利用data.table的矢量化优势。
问题分析
你原来的代码:
for (col in colnames(dt)) dt[is.na(get(col)), (col) := rnorm(1,mean=(avg),sd=(stdev))]
这里的rnorm(1,...)只会生成一个随机数,然后把该列所有NA都替换成这个数——但不同行的NA对应的avg和stdev是不一样的,所以结果肯定不符合预期。
正确的解决方案
我们可以利用data.table的矢量化操作,高效地为每个NA位置生成对应行参数的随机数,代码如下:
library(data.table) # 构造你的数据表 dt <- data.table( V1 = c(-1, NA, 10), V2 = c(-2, 3, 15), V3 = c(NA, 5, 20), V4 = c(NA, NA, NA), V5 = c(-3, 7, NA), avg = c(-2, 5, 15), stdev = c(.82, 1.63, 4.08) ) # 1. 定义需要填充NA的列(排除avg和stdev) cols_to_fill <- setdiff(colnames(dt), c("avg", "stdev")) # 2. 矢量化填充NA:为每个NA生成对应行参数的随机数 dt[, (cols_to_fill) := lapply(.SD, function(col) { # 对每一列,用对应行的avg/stdev生成随机数替换NA ifelse(is.na(col), rnorm(.N, mean = avg, sd = stdev), col) }), .SDcols = cols_to_fill] # 查看结果 print(dt)
代码解释
cols_to_fill:筛选出需要处理的列(V1到V5),避免修改avg和stdev列;.SDcols = cols_to_fill:告诉data.table只在指定列上操作;lapply(.SD, function(col) {...}):对每个目标列进行处理;rnorm(.N, mean = avg, sd = stdev):生成一个与数据表行数相同的随机数向量,每个元素对应该行的均值和标准差;ifelse(is.na(col), ..., col):精准替换列中的NA位置,非NA值保持不变。
可选优化:可重复的随机数
如果需要固定生成的随机数(方便调试或复现结果),可以在运行代码前设置随机种子:
set.seed(123) # 任意数字都可以
这样处理后,每行的NA都会被对应行参数生成的正态随机数替换,完全符合你的需求。
内容的提问来源于stack exchange,提问作者FG7
相关产品推荐
相关产品推荐

