基于多重插补结果创建分类变量及被动插补报错问题咨询
问题描述
我有1000条样本数据,包含连续变量与分类变量,存在缺失值。需要基于多重插补后的结果,为每个样本标记class(class A、B、C)分类变量。
我首先参考《Flexible imputation of missing data, 2nd ed.》中6.4章节的方法尝试实现,代码如下:
imp1 <- mice(df, maxit = 5, pred = pred ,method =meth, post=post, print = TRUE, allow.na=TRUE) long1 <- mice::complete(imp1, "long", include=TRUE) long2<-long1 %>% rowwise() %>% mutate(class = case_when(sum(var1 == 1, var2 > 15, var3 == 1, var4 == 2, var5 < 2.0) >= 2 ~ 'class A', sum(var1 == 1, var2 > 15, var3 == 1, var4 == 2, var5 < 2.0) == 1 & sum((var2 >= 15 & var2 < 25), var4 == 1) > 1 ~ 'class B', TRUE ~ 'class C')) imp1.itt <- as.mids(long2)
Q1:请问该方法是否可行?
Q2:是否可以通过被动插补(passive imputation)实现?我尝试了以下代码:
df1<-cbind(df, class=NA) ini<-mice(df1, max=0, print=FALSE) pred<-ini$predictorMatrix pred[, c( 'class')]<-0 meth<-ini$method meth['class']<-"~case_when(sum(var1 == 1, var2 > 15, var3 == 1, var4 == 2, var5 < 2.0) >= 2 ~ 'class A', sum(var1 == 1, var2 > 15, var3 == 1, var4 == 2, var5 < 2.0) == 1 & sum((var2 >= 15 & var2 < 25), var4 == 1) > 1 ~ 'class B', TRUE ~ 'class C')" imp <- mice(df1, maxit = 5, predictorMatrix = pred,method =meth, print = TRUE, allow.na=TRUE)
但运行时出现错误:Error in colMeans(as.matrix(imp[[j]]), na.rm = TRUE) : 'x' must be numeric,请问问题出在哪里?
示例数据集
df2 <- read.table(text = " var1 var2 var3 var4 var5 id1 1 10 1 0 1.5 id2 0 20 0 1 2.4 id3 0 15 0 1 3.5 id4 1 30 1 1 2.1", header = TRUE)
解答
Q1:方法可行性分析
该方法可行,但需注意几个细节:
rowwise()处理1000条数据效率尚可,若后续数据量增大,建议用rowSums()做向量化操作替代,减少逐行循环的开销。as.mids(long2)要确保long格式中的.imp、.id列与原始插补的分组、样本ID对应,否则后续基于mids对象的分析可能出错。- 确认
sum(var1 ==1,...)的逻辑:这里sum()会将布尔值转为1/0求和,逻辑正确,但要保证long1中无缺失值(complete(..., include=TRUE)已包含原始数据和所有插补数据集)。
Q2:被动插补报错原因与修正
报错原因
mice的被动插补(公式形式)默认期望生成数值型变量,而你的class是字符型分类变量,as.matrix(imp[[j]])会将字符型列转为因子或保留字符,导致colMeans()无法计算(仅支持数值型矩阵),因此抛出错误。
修正方案
有两种可行思路:
思路1:先编码为数值,插补后转回分类标签
df1<-cbind(df, class=NA) ini<-mice(df1, max=0, print=FALSE) pred<-ini$predictorMatrix pred[, 'class']<-0 # 先将分类逻辑转为数值编码 meth['class']<-"~{ score1 <- sum(var1 == 1, var2 > 15, var3 == 1, var4 == 2, var5 < 2.0) score2 <- sum((var2 >=15 & var2 <25), var4 ==1) ifelse(score1 >=2, 1, ifelse(score1 ==1 & score2 >1, 2, 3)) }" imp <- mice(df1, maxit =5, predictorMatrix=pred, method=meth, print=TRUE) # 插补完成后将数值转回分类标签 imp$imp$class <- lapply(imp$imp$class, function(x) { factor(x, levels=c(1,2,3), labels=c('class A','class B','class C')) })
思路2:自定义被动插补函数处理分类变量
mice允许自定义插补方法,针对分类变量写专属函数:
# 定义分类变量的被动插补函数 passive_class <- function(data, ...) { score1 <- rowSums(cbind(data$var1 ==1, data$var2 >15, data$var3 ==1, data$var4 ==2, data$var5 <2.0)) score2 <- rowSums(cbind(data$var2 >=15 & data$var2 <25, data$var4 ==1)) class <- case_when( score1 >=2 ~ 'class A', score1 ==1 & score2 >1 ~ 'class B', TRUE ~ 'class C' ) return(class) } df1<-cbind(df, class=NA) ini<-mice(df1, max=0, print=FALSE) pred<-ini$predictorMatrix pred[, 'class']<-0 meth<-ini$method meth['class'] <- "passive_class" # 注册自定义方法 mice::mice.add.method("passive_class", passive_class, "Passive imputation for class variable", TRUE) imp <- mice(df1, maxit=5, predictorMatrix=pred, method=meth, print=TRUE)
内容的提问来源于stack exchange,提问作者JY J
相关产品推荐
相关产品推荐

