数据缺失的类型在统计学和医学研究中主要依据缺失机制(missing mechanism)进行分类,国际公认的标准分为三种,这一分类最早由Rubin(1976)提出,被广泛应用于临床试验、流行病学和生物统计领域。
一、完全随机缺失(MCAR, Missing Completely at Random)

一、删除法(Deletion Methods)


三、模型直接处理法(Model-Based Approaches)
某些模型原生支持缺失值,无需预处理:决策树/随机森林/XGBoost:通过“代理分裂”处理缺失;贝叶斯网络:将缺失视为隐变量;全信息最大似然(FIML):在结构方程模型(SEM)中直接使用不完整数据 。
四、将缺失作为信息(Missingness as a Feature)
创建指示变量(Indicator Variable):新增一列标记“是否缺失”(0/1),与原始变量一起纳入模型;虚拟类别法:对分类变量,将缺失设为单独一类(如性别:男、女、未知);适用场景:缺失本身有临床意义(如患者拒答代表态度);MNAR缺失的探索性分析。
小结:
mice包是R语言中用于处理缺失数据的权威工具包,全称为Multivariate Imputation by Chained Equations(多元链式方程多重插补)。它通过多重插补(Multiple Imputation, MI)方法,为包含缺失值的数据集生成多个完整版本,从而在保留样本信息的同时,合理反映缺失带来的不确定性。MICE算法可以处理多种类型的数据混合情况,包括:连续型变量;二元变量;无序分类变量;有序分类变量。
使用数据是含有年龄和血脂相关指标的示例数据,其中年龄数据是完整的。
rm(list = ls())
proj = "test"
library(dplyr)
library(stringr)
library(xlsx)
library(mice)
dat <- read.xlsx("./testData.xlsx",sheetIndex = 1)
head(dat)
# age CHOL TG HDL LDL
# 1 61 4.77 2.01 0.78 2.79
# 2 64 5.28 2.13 0.89 3.04
# 3 22 4.48 0.69 1.34 2.59
# 4 43 3.34 0.92 1.10 1.57
# 5 36 4.40 0.75 1.04 2.52
# 6 76 6.12 0.93 1.23 3.76查看了不同数据的确实百分比,大概都在20%多。
missing_pct <- mean(is.na(dat$CHOL)) * 100;missing_pct
# [1] 22.05882
missing_pct <- mean(is.na(dat$TG)) * 100;missing_pct
# [1] 22.05882
missing_pct <- mean(is.na(dat$HDL)) * 100;missing_pct
# [1] 22.05882
missing_pct <- mean(is.na(dat$LDL)) * 100;missing_pct
# [1] 23.52941
# 对于缺失数据进行插补
mice_vars <- dat
mice_vars$age <- as.numeric(mice_vars$age)
mice_vars$CHOL <- as.numeric(mice_vars$CHOL)
mice_vars$TG <- as.numeric(mice_vars$TG)
mice_vars$HDL <- as.numeric(mice_vars$HDL)
mice_vars$LDL <- as.numeric(mice_vars$LDL)
str(mice_vars)
# 'data.frame': 136 obs. of 5 variables:
# $ age : num 61 64 22 43 36 76 58 31 51 80 ...
# $ CHOL: num 4.77 5.28 4.48 3.34 4.4 6.12 4.58 3.71 4.72 6.08 ...
# $ TG : num 2.01 2.13 0.69 0.92 0.75 0.93 1.41 1.2 1.8 4.05 ...
# $ HDL : num 0.78 0.89 1.34 1.1 1.04 1.23 1.4 1.09 0.97 0.96 ...
# $ LDL : num 2.79 3.04 2.59 1.57 2.52 3.76 2.13 1.89 2.85 3.31 ...
# 查看数据缺失情况
md.pattern(mice_vars)
# age CHOL TG HDL LDL
# 104 1 1 1 1 1 0
# 2 1 1 1 1 0 1
# 30 1 0 0 0 0 4
# 0 30 30 30 32 122列表示不同变量名称:age, CHOL, TG, HDL, LDL;
行表示不同的“缺失模式”(missing pattern)。每行代表一组具有相同缺失结构的观测值。
颜色:蓝色该变量在这一模式下是有观测值(非缺失);红色该变量在这一模式下是缺失(NA)。
数字:每行最左侧的数字(如 104, 2, 30)表示具有该模式的样本数量,右侧的数字(0,1,4)表示缺失模式。每列最下方的数字(如 0, 30, 30...)表示该变量总的缺失次数。

# 数据是连续型,所以用lm;二分类就用glm
imp <- mice(mice_vars, seed = 123, print = FALSE, m=5)
fit <- with(imp, lm( age~ CHOL+TG + HDL + LDL))
# 汇总结果
est1 <- pool(fit)
# 查看汇总结果
summary(est1)
# term estimate std.error statistic df p.value
# 1 (Intercept) 49.4308196 5.588920 8.84443107 97.29783 4.090503e-14
# 2 CHOL 0.3542238 5.158658 0.06866588 55.80299 9.455010e-01
# 3 TG 0.3505387 1.191522 0.29419414 59.18127 7.696390e-01
# 4 HDL 2.4273011 7.037169 0.34492579 39.15819 7.319960e-01
# 5 LDL -0.3311654 5.985305 -0.05532974 59.38803 9.560615e-01
# 提取第一次插补的结果
imputed_df <- mice::complete(imp, action = 1)
# action可以根据后面的内容进行选择:c("all", "long", "broad", "repeated", "stacked")
# 在多重插补结果的提取中,complete函数提供了多种格式选项:"all"返回一个包含所有插补数据集的列表,若设置include =TRUE,还会将原始含缺失值的数据作为第一个元素;"long"将各插补数据集纵向堆叠成一个长格式数据框,并新增.imp(插补编号)和.id(原始行标识)两列;"stacked"与"long"类似,但不包含这两列;"broad"将插补数据集横向拼接为宽格式,每个变量的列名后附加插补编号(如Ozone.1,Ozone.2),且列顺序与原始数据一致;而"repeated"同样是横向展开,但列按插补编号分组排列(即先列出所有第1次插补的变量,再是第2次的,依此类推)
# 诊断图绘制
bwplot(imp)
# 密度图绘制
densityplot(imp,layout = c(4, 1))四个子图:分别对应CHO、T、HD、LDL四个变量;
横轴:表示插补编号(0 到 5),其中:0表示原始观测值(即未缺失的数据);1到5表示第 1 到第 5 次插补生成的值;
纵轴:表示变量的数值;
箱线图:红色箱线图表示每次插补中该变量所有插补值的分布;蓝色箱线图(仅在0处)表示原始观测值的分布;

这个图跟上面的图判读也类似,红色的线与蓝色的线重合的越好则代表插补模型合理。

imputed_df左边是插补前,右边是插补后的数据。按照不同的m值可以得到m个插补数据,随机选择其中一个即可,如果更加严谨的话还需要进行统计判断。此外,作者不建议对m次结果求均值纳入分析,也不建议把m次结果都纳入进分析。

# 可以稍微看一下每个参数的作用
mice(
data,
m = 5, # 多重插补的次数,默认值为5
method = NULL,
predictorMatrix, # 默认情况每个变量都用其他所有变量作为预测因子
ignore = NULL,
where = NULL, # 可以指定插补的位置,默认是全部的NA
blocks,
visitSequence = NULL, # visitSequence = "roman" 表示按照 blocks 列表中从左到右的顺序依次访问各块。
formulas,
calltype = NULL,
blots = NULL,
post = NULL,
defaultMethod = c("pmm", "logreg", "polyreg", "polr"), # 数值型用预测均值匹配(pmm),二元因子用逻辑回归(logreg),无序多分类因子用多项回归(polyreg),有序多分类因子用比例优势模型(polr)。
maxit = 5,
printFlag = getOption("mice.printFlag", TRUE),
seed = NA,
data.init = NULL,
...
)注:若对内容有疑惑或者有发现明确错误的朋友,请联系后台。更多相关内容可关注公众号:生信方舟 。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。