【问题标题】:r data.table impute missing values for multiple set of columnsr data.table 为多组列估算缺失值
【发布时间】:2018-12-25 00:25:22
【问题描述】:

我想估算几列的缺失值。这个想法是对于我想使用 median 来估算 NA 的数值变量和我想使用 mode 来估算 NA 的分类变量。我确实搜索了如何为不同的列集单独估算它,但没有找到。

我的数据很大,有很多列,所以我把它放在 data.table 中。由于我不确定如何在 data.table 中执行此操作,因此我尝试了下面的代码库 R。我尝试了下面的代码,但不知怎的,我似乎搞乱了列名标识。

我的数据很大并且包含多个变量。我将数值变量存储在向量 var_num 中,并将分类变量存储在向量 var_chr 中。

请看下面我的示例代码 -

library(data.table)
set.seed(1200)
id <- 1:100
bills <- sample(c(1:20,NA),100,replace = T)
nos <- sample(c(1:80,NA),100,replace = T)
stru <- sample(c("A","B","C","D",NA),100,replace = T)
type <- sample(c(1:7,NA),100,replace = T)
value <- sample(c(100:1000,NA),100,replace = T)

df1 <- as.data.table(data.frame(id,bills,nos,stru,type,value))
class(df1)

var_num <- c("bills","nos","value")
var_chr <- c("stru","type")

impute <- function(x){
  #print(x)
  if(colnames(x) %in% var_num){
    x[is.na(x)] = median(x,na.rm = T)
  } else if (colnames(x) %in% var_chr){
    x[is.na(x)] = mode(x)
  } else {
    x #if not part of var_num and var_chr then nothing needs to be done and return the original value
  }
  return(x)
}


df1_imp_med <- data.frame(apply(df1,2,impute))

当我尝试运行上面的代码时,它给了我错误Error in if (colnames(x) %in% var_num) { : argument is of length zero

请帮助我了解如何纠正此问题并实现我的要求。

【问题讨论】:

  • 如果您使用的是data.table,您应该考虑利用它的功能,例如使用:= assingment 进行引用更新,或者在这种情况下可能更适合for + @987654328 @ 遍历多个列。

标签: r function data.table missing-data imputation


【解决方案1】:

另一个使用lapply的选项

lapply(c(var_num, var_chr), function(x){ 
  imp.fun <- ifelse(x %in% var_num
                   , function(x) median(x, na.rm = T) 
                   , function(x) names(which.max(table(x))))
  df1[is.na(df1[[x]]), (x) := imp.fun(df1[[x]])]})

【讨论】:

  • 该代码无法运行,但有类似的imp = df1[, c(lapply(.SD[, ..var_num], median, na.rm = TRUE), lapply(.SD[, ..var_chr], getMode))]; for (k in c(var_num, var_chr)) df1[is.na(get(k)), (k) := imp[[k]]][](getMode 借自 caw 的答案)
【解决方案2】:

按照 cmets 中的建议,您可以在 data.table 中使用for-set 组合来更快地进行插补:

for(k in names(df1)){

      if(k %in% var_num){

        # impute numeric variables with median
        med <- median(df1[[k]],na.rm = T)
        set(x = df1, which(is.na(df1[[k]])), k, med)

    } else if(k %in% var_char){

        ## impute categorical variables with mode
        mode <- names(which.max(table(df1[[k]])))
        set(x = df1, which(is.na(df1[[k]])), k, mode)
    }
}

【讨论】:

  • 感谢您的回答。我想参考 var_num 和 var_chr 中指定的变量.....您的解决方案将对所有列进行插补。但是,是的,这将是一个很好的参考。
  • 这是我无法立即提出的通用解决方案 ;) 注意 OP,使用这种方法,df1 的“类型”列需要更改为要计算的因子或字符模式而不是中位数(因为它是一个数字向量,但需要模式)
  • @user1412 我以前使它更通用,这样您就不需要对列名进行硬编码,只需更新答案即可。
  • @YOLO 谢谢!!
【解决方案3】:

我设法找到了一个可行的解决方案。关键之一是引用 var_numvar_chr 中指定的变量进行数值和分类插补。这些向量中未指定的变量不需要进行插补。

我面临的挑战是在函数中引用它们。我放弃了编写函数的想法,并设法编写了一个 for 循环,如下所示 -

df1 <- as.data.frame(df1)

for (var in 1:ncol(df1)) {
  if (names(df1[var]) %in% var_num) {
    df1[is.na(df1[,var]),var] <- median(df1[,var], na.rm = TRUE)
  } else if (names(df1[var]) %in% var_chr) {
    df1[is.na(df1[,var]),var] <- names(which.max(table(df1[,var])))
  }
}

这个for循环会进行所需的插补。

如果有更多更简单简洁的方法来实现这一点,请告诉我。也许一些申请家庭可以做到这一点。

【讨论】:

    【解决方案4】:

    为两个用例编写一个函数可能值得,也可能不值得。下面是一个直接(但具体)的解决方案——请注意mode 的行为可能与您预期的不同,请阅读?mode

    library(data.table)
    
    set.seed(1200)
    df1 <- data.table(
    id = 1:100,
    bills = sample(c(1:20,NA),100,replace = T),
    nos = sample(c(1:80,NA),100,replace = T),
    stru = sample(c("A","B","C","D",NA),100,replace = T),
    type = sample(c(as.character(1:7),NA),100,replace = T),
    value = sample(c(100:1000,NA),100,replace = T)
    )
    
    # Function to calculate the most frequent object in a vector:
    getMode <- function(myvector) {
        mytable <- table(myvector)
        return(names(mytable)[which.max(mytable)])
    }
    
    # replace na values by reference, with `:=`
    df1[is.na(bills), bills := median(df1[,bills], na.rm=T)]
    df1[is.na(nos), nos := median(df1[,nos], na.rm=T)]
    df1[is.na(value), value := median(df1[,value], na.rm=T)]
    df1[is.na(stru), stru := getMode(df1[,stru])]
    df1[is.na(type), type := getMode(df1[,type])]
    

    【讨论】:

    • 感谢您的回答。是的,我得到的模式在 R 中是不同的,并且使用名称的组合(其中(表....请参阅我的答案。正如您所提到的,这将是一个很长的方法,因为有很多变量......跨度>
    猜你喜欢
    • 1970-01-01
    • 2020-06-19
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多