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

时间:2018-07-17 10:24:49

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

我想为几组列估算缺失值。我的想法是针对要使用中位数的数字变量来归纳NA,对于归类变量,我要使用 mode 来归纳{{1 }}。我确实搜索了如何针对不同的列集分别进行插补,但没有找到。

我的数据很大,有很多列,所以我将其保存在 data.table 中。由于我不确定如何在data.table中执行此操作,因此我尝试在代码库R下进行尝试。我曾尝试在下面的代码中进行尝试,但是不知何故,我似乎弄乱了列名的标识。

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

请在下面查看我的示例代码-

NA

当我尝试运行上面的命令时,它给我错误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))

请帮助我了解如何解决此问题并达到要求。

4 个答案:

答案 0 :(得分:3)

如注释中所建议,您可以在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)
    }
}

答案 1 :(得分:1)

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

答案 2 :(得分:0)

我设法找到了可行的解决方案。关键之一是要引用 var_num var_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循环执行所需的估算。

如果还有更多更简单简洁的方式来实现此目标,请告诉我。也许有些应征家庭可以解决这个问题。

答案 3 :(得分:0)

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