r data.table 为多组列估算缺失值

r data.table impute missing values for multiple set of columns

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

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

我的数据很大并且有多个变量。我将数值变量存储在向量 var_num 中,我将分类变量存储在向量 var_chr.[=15= 中]

请看下面我的示例代码-

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 中使用 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)
    }
}

您可能值得也可能不值得花时间为您的两个用例编写一个函数。下面是一个直接(但具体)的解决方案——请注意 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])]

我设法找到了可行的解决方案。关键之一是参考 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 循环 执行所需的插补。

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

另一个选项使用 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]])]})