根据sd和每行的平均值将NA替换为随机正常数

时间:2018-01-14 00:36:56

标签: r 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))

看起来像:

        V1  V2  V3  V4  V5  avg stdev
    1   -1  -2  NA  NA  -3  -2  0.82
    2   NA  3   5   NA  7   5   1.63
    3   10  15  20  NA  NA  15  4.08

我想用正态分布的随机数替换每个NA,使用avg列的平均值和stdev列的标准偏差。例如,在第1行中,我想要使用mean = -2和sd = 0.82计算两个随机数(以替换V3中的NA,V4)。在第2行中,我想要使用mean = 5和sd = 1.63等计算两个随机数(以替换V1中的NA,V4)等。所有行的逻辑相同。我试过这个并没有按预期工作:

    for (col in colnames(dt)) dt[is.na(get(col)), (col) := rnorm(1,mean=(avg),sd=(stdev))]

我欢迎任何想法。感谢。

2 个答案:

答案 0 :(得分:2)

你非常接近。

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))

# change V4 to numeric, otherwise is logical
dt[, V4 := as.numeric(V4)]

set.seed(1234)
for (col in names(dt)[1:5]){
    # rnorm() is more annoying than expected, n = 1 cannot recycle
    dt[is.na(get(col)), (col) := as.numeric(rnorm(rep(1, sum(is.na(get(col)))), avg, stdev))]
}

#           V1 V2        V3        V4       V5 avg stdev
# 1: -1.000000 -2 -1.772508 -1.110758 -3.00000  -2  0.82
# 2:  3.032483  3  5.000000  1.176513  7.00000   5  1.63
# 3: 10.000000 15 20.000000 16.750829 17.06471  15  4.08

答案 1 :(得分:1)

我将假设avgstdev列没有任何特殊之处,它们只是行方式和标准偏差。

首先是助手插补功能

impute <- function(x) {
  avg <- mean(x, na.rm = TRUE)
  stdev <- sd(x, na.rm = TRUE)
  indices <- which(is.na(x))
  x[indices] <- rnorm(length(indices), avg, stdev)
  x
}

接下来删除avgstdev列。

no_avg <- dt[, !(colnames(dt) %in% c("avg", "stdev"))]

然后按行impute行。 data.tablet只是让我们回到原来的格式。

data.table(t(apply(no_avg, 1, impute)))