【问题标题】:Fill missing values with linear regression用线性回归填充缺失值
【发布时间】:2020-08-28 03:01:51
【问题描述】:

我有一个包含 7 列的数据框。

 str(df)

'data.frame':   8760 obs. of  7 variables:
 $ G1_d20_2014.SE1_ : num  25.1 25.1 25 25 25.1 ...
 $ G1_d20_2014.SE4_ : num  42.4 42.3 42.3 42.3 42.3 ...
 $ G1_d20_2014.SE7_ : num  34.4 34.4 34.4 34.4 34.4 ...
 $ G1_d20_2014.SE22_: num  42.5 42.4 42.3 42.4 42.3 ...
 $ G1_d20_2014.SE14_: num  52.5 52.5 52.5 52.5 52.4 ...
 $ G1_d20_2014.SE26 : num  40.8 40.8 40.8 40.8 40.8 ...

每一列代表一个唯一的传感器,并且这些列包含来自传感器的测量数据。某些列包含缺失值。我想通过线性回归填补每列中的数据空白。我已经手动完成了此操作,但有一个非常重要的条件,我正在寻找一个可以自行执行此操作的函数,因为为所有列执行此操作需要太多时间。这是条件: 假设 G1_d20_2014_SE1 包含缺失数据。 然后我想用相关系数最高的另一个传感器的完整数据集来填补该传感器的数据空白

这是我手动操作的方法:

我创建了一个创建指标变量的函数。如果值不是 NA,则指示变量变为 1,如果值为 NA,则变为 0。然后我将此变量作为列添加到数据集中:

Indvar <- function(t) {

  x <- dim(length(t))
  x[which(!is.na(t))] = 1
  x[which(is.na(t))] = 0 
  return(x)
}

df$I <- Indvar(df$G1_d20_2014.SE1_)

接下来我查看了哪个传感器和传感器 1 之间的相关系数最高(在这种情况下,SE1 和 SE14 之间的相关系数最高)。然后我计算了线性回归,从中取出方程并将其放入一个 for 循环中,每当指标变量为 0 时,根据方程填充 NA 值:

lm(df$G1_d20_2014.SE1_ ~ df$G1_d20_2014.SE14_, data = df)

for (i in 1:nrow(df)) {

  if (df$I[i] == 0)

  {

    df$G1_d20_2014.SE1_[i] = 8.037 + 0.315*df$G1_d20_2014.SE14_[i]
  }
}

这工作得很好,但是这样做需要太多时间,因为我有很多看起来像帖子中的数据框。

我已经尝试使用 simputation 包中的 impute_lm ,但不幸的是,在填补数据空白之前,它似乎并不关心相关性最高的位置。这是我写的:

impute_fun <- impute_lm(df, 
    formula = SE1_ + SE4_ ~ SE14_ + SE26)

在我写SE14_ + SE26_ 时,我检查了他是否使用 SE14 中的值来估算 SE1 中的值,但他没有,因为结果与我的手动结果不同。

有什么功能可以满足我的需求吗?我真的很沮丧,因为我已经找了两个多星期了。我真的很感激一些帮助!

编辑/回复@jay.sf

所以我尝试用它制作一个函数(如下所示),但我遇到了一些困难:

我不知道如何在函数中指定我想为每一列执行此操作,并且它会从 sapply(c("SE1_", "SE2_ ", ...) 因为显然,如果我对 SE1_ 执行此操作,并且 SE1_ 仍在代码中,则相关性将为 1,并且什么也没有发生。现在您可以看到,这对于其余代码也是有问题的,例如在行 cor(df$SE1_, df[, x], use = "complete.obs")) 正如它所说的 df$SE1_ 在这里。 df$SE1_imp

我尝试像这样运行代码(但当然在 sapply(...) 中没有 SE1_),我得到了错误:df[, x] 中的错误:维数不正确。 任何想法如何解决这些问题?

      impFUN <- function(df) {

      corr <- sapply(c("SE1_", "SE2_", "SE4_", "SE5_","SE6_",                      
                      "SE7_", "SE12_", "SE13_","SE14_", "SE15_",
                      "SE16_", "SE22_","SE23", "SE24", "SE25",
                      "SE26",  "SE33", "SE34", "SE35", "SE36",
                      "SE37", "SE46", "SE51", "SE52", "SE53",
                      "SE54", "SE59", "SE60", "SE61", "SE62", 
                      "SE68", "SE69", "SE70", "SE71", "SE72", 
                      "SE73","SE74", "SE82", "SE83", "SE84", 
                      "SE85", "SE86", "SE87", "SE99","SE100", 
                      "SE101", "SE102", "SE103","SE104", 
                      "SE106", "SE107","SE121"),  function(x)
                  cor(df$SE1_, df[, x], use = "complete.obs")) 

      imp.use <- names(which.max(corr)) 

      regr.model <- lm(reformulate(imp.use, "SE1_"))

      df$SE1_imp <- 
          ifelse(is.na(df$SE1_), lm.cf[1] + df[[imp.use]]*lm.cf[2], df$SE1_)

    }

【问题讨论】:

  • 如果我理解正确,您要做的是根据df$G1_d20_2014.SE14df$G1_d20_2014_ 中的非缺失值 建立一个线性模型以填写df$G1_d20_2014.SE1 的 i>缺失 值。与其分别预测每个缺失的数据点,不如将其向量化?例如,mod &lt;- lm(df$G1_d20_2014.SE1_[df$I==1] ~ df$G1_d20,2014.SE14_[df$I==1]); df$G1_d20_2014.SE1[df$I==0] &lt;- predict(mod, df$G1_d20_2014.SE14[df$I==0])

标签: r imputation


【解决方案1】:

这个呢?首先检查哪个传感器与传感器 1 最相关。

corr <- sapply(c("sensor.2", "sensor.3", "sensor.4"), function(x) 
  cor(dat$sensor.1, dat[,x], use="complete.obs"))
#   sensor.2    sensor.3    sensor.4 
# 0.04397132  0.26880412 -0.06487781 

imp.use <- names(which.max(corr))
# [1] "sensor.3"

计算回归模型,

lm.cf <- lm(reformulate(imp.use, "sensor.1"), dat)$coef

要估算传感器 1,请使用 ifelse 中的系数,如下所示:

dat$sensor.1.imp <- 
  ifelse(is.na(dat$sensor.1), lm.cf[1] + dat[[imp.use]]*lm.cf[2], dat$sensor.1)

结果

head(dat)
#     sensor.1   sensor.2   sensor.3    sensor.4 sensor.1.imp
# 1  2.0348728 -0.6374294  2.0005714  0.03403394    2.0348728
# 2 -0.8830567 -0.8779942  0.7914632 -0.66143678   -0.8830567
# 3         NA  1.2481243 -0.9897785 -0.36361831   -0.1943438
# 4         NA -0.1162450  0.6672969 -2.84821295    0.2312968
# 5  1.0407590  0.1906306  0.3327787  1.16064011    1.0407590
# 6  0.5817020 -0.6133034  0.5689318  0.71543751    0.5817020

玩具数据:

library('MASS')
set.seed(42)
M <- mvrnorm(n=1e2, mu=c(0, 0, 0, 0), 
             Sigma=matrix(c(1, .2, .3, .1,
                            .2, 1, 0, 0, 
                            .3, 0, 1, 0,
                            .1, 0, 0, 1), nrow=4),
             empirical=TRUE)
dat <- as.data.frame(`colnames<-`(M, paste0("sensor.", 1:4)))
dat[sample(1:nrow(dat), 30), "sensor.1"] <- NA  ## generate 30% missings

【讨论】:

  • 这很好。但是,问题仍然是我必须检查每个传感器的最高相关性。正如我所说,这对于一个数据框来说不是问题,但我有 74 个其他数据框,其中一些包含 48 个传感器的数据,像这样手动完成需要太长时间。我想知道是否有可能编写一个函数,自动为每个传感器获取最高相关性,然后自行执行上述操作。
  • 只需将其包装成一个函数impFUN &lt;- function(dat) {corr &lt;- ... imp.use &lt;- ...lm.cf &lt;- ... ifelse(...)},然后使用lapply(list(dat1, dat2, ... dat48), impFUN)
  • 我知道这是不久前的事了,但是我遇到了问题。由于您的解决方案仅使用具有最高相关性的传感器来“填充”间隙,因此如果另一个传感器在与我要填充的传感器相同的位置存在数据间隙,则会出现问题。您是否知道如何在代码中设置一个条件,即如果第一个不能填补空白,那么它采用具有第二高相关性的传感器,然后是第三个,依此类推......?
  • 我知道如何计算第二个最大值(参见下面的代码),但我不知道如何在代码中实现它。如果你能帮助我,那就太好了! l = length(corr)secondmax &lt;- sort(corr, partial = l-1)[l-1]
猜你喜欢
  • 2022-01-06
  • 1970-01-01
  • 2019-12-29
  • 2019-02-01
  • 2012-10-25
  • 2017-10-21
  • 1970-01-01
相关资源
最近更新 更多