想象你是年夜饭的主厨,面前摊开一张采购单:每一行是一道菜,每一列是一种配料。可清单上总有几格空着——糖醋排骨的“糖”没写克数,酸菜鱼的“酸菜”用量被酱油浸花了。这就是缺失值:数据表里那些空荡荡的格子。直接把缺料的菜划掉?客人爱吃的菜没了。随便填个数?整桌菜的味道都毁了。好在老主厨们有一套“补料哲学”:先弄清楚空格是怎么来的,再决定是划掉菜、借邻居的料、按配方推算,还是请几位师傅各补一版。这就是缺失值插补——用合理数值填补空缺,最大程度保住数据里的信息。从均值填补到 KNN、回归、多重插补,这篇文章带你把这套厨房经验变成建模手艺。
缺失值插补是特征工程的基本功。学会它,你就能在数据清洗环节少丢信息、少引偏差,让后续每个模型都站在更扎实的数据地基上,是 AI 从业者必备的“救场”能力。
可视化演示
展示数据缺失场景下不同插补策略的效果:从原始缺失数据到均值填补、KNN近邻插补、回归插补,直观对比各方法的填充质量与偏差。
本节配有交互动效(进入视口后自动加载,约 3KB)。
原始数据缺失分布 实心点为完整数据空心点为缺失值 缺失率18%直接影响建模质量 选择插补方法查看填充效果
缺失值认知
年夜饭前夜,主厨老张对着采购单发愁:二十道菜的配料清单里,有几格是空的——糖醋排骨的“糖”没写克数,酸菜鱼的“酸菜”用量模糊不清。表格就是数据集的缩影:每一行是一道菜(样本),每一列是一种配料(特征),空着的格子就是缺失值。任何真实数据采集都免不了留下空格——患者病历漏掉血压,信贷申请表漏掉收入,传感器在断电的那几分钟没记录。这些空单元格在程序里通常用 NaN 或 null 表示,而大多数机器学习算法无法直接吞下它们,就像没写用量的菜谱没法直接开火。
缺失值带来的麻烦有两层。其一是信息量损失:你辛苦记录了十几列完整信息,却因为一列空白,整行样本在很多算法里都派不上用场。其二是偏差风险:如果空白不是随机出现的——比如高收入人群总是不填收入——那么无视它,模型就会偷偷学偏。工程上,用 df.isna().sum() 可以快速盘点每个特征各缺多少,这一步叫“缺失值探测”,它是所有补救工作的起点。
老张要做的第一件事不是急着补料,而是把采购单摊开,数清楚到底哪几道菜缺料、缺了多少。认识缺失值,是补料的第一步。
缺失机制
老张凑近采购单,发现空格的来历各不相同:一张菜谱被酱油瓶打翻浸湿了一角,三个格子糊成一团——这纯粹是意外;标注“特辣”的几道菜,辣度栏总是空着——空格似乎和已填的口味档位有关;还有一道“祖传秘方”菜,关键配料栏永远空白,因为只有老张自己知道用量——空格和缺失的值本身直接相关。统计学家把这三类情况称为 MCAR、MAR 和 MNAR。
MCAR(完全随机缺失):缺失与否和任何数据都无关,就像那角被酱油浸湿的菜谱,纯属天灾。MAR(随机缺失):缺失与已观测到的其他变量有关,但与缺失值本身无关——辣度栏空不空,取决于是否标注了“特辣”,而特辣是已经观测到的信息。MNAR(非随机缺失):缺失与否与缺失值本身有关——秘方配料从不写出来,恰恰因为它是“秘方”。MCAR 是理想情形,删行损失最小;MAR 是多数插补方法能处理的范围;MNAR 最棘手,常需结合业务知识单独建模。
如何判断机制?实务中常比较“缺失组”和“完整组”在其他变量上有没有显著差异——比如辣度缺失的菜是不是清一色标了特辣。再有就是业务经验。老张明白了:酱油浸湿的格子可以直接扔掉重写(删除),特辣菜的空格能参照同类菜谱补上(插补),但“秘方”那一栏,任何人都没法替他填——机制决定了补救的可能性和代价。
- 缺失指示变量R 下标 ij 表示“第 i 行第 j 列是否缺失”,取 1 代表缺失,取 0 代表已观测。
- 条件概率P(R=1 | X) 读作“给定数值 X 的条件下发生缺失的概率”,它刻画缺失是否依赖数值本身。
- MCAR 的等式如果这个条件概率恒等于整体缺失率,说明缺失和数值无关,即完全随机缺失。
处理策略
面对空格,老张有三条路:把缺料的菜从菜单上划掉——这是删除法;翻其他菜谱找替代用量——这是填补法;或者干脆凭老经验模糊估计,让炉火大小去将就——这是不处理。三条路各有利弊,得看缺料的情况来选。
删除法是最朴素的对策:删除含缺失值的整行(listwise deletion),甚至整列(当某列缺失过多时)。它适合缺失比例低(一般 <5%)且机制为 MCAR 的场景。缺点也很明显:删行损失样本量,删列损失特征信息。填补法则是用合理数值替换空格,是这篇文章的主角,从简单的均值到复杂的多重插补都属于它。不处理方案听起来偷懒,却有道理可讲:部分树模型(如 XGBoost、LightGBM)在训练时能自动学习“缺失方向”作为分裂依据,天然容忍缺失;但线性回归、神经网络等绝大多数模型做不到,遇到缺失只会报错或学偏。
一个务实的经验口诀:缺失比例 <5% 且 MCAR,删除行可接受;5%~20%,优先填补;>20%,这个特征的信息价值要大打折扣,考虑删列或上更复杂的插补。填补绝不是越复杂越好,要综合权衡数据量、缺失机制和下游任务。老张最终决定:那道缺料太多又冷门的菜划掉,主力硬菜用填补法救回来——删除和填补从来不是对立的,而是一套组合拳。
简单填补法
最省事的替补方案,是去超市买一包“万能调味料”:不管缺的是糖是盐,都按整个厨房平时的平均用量倒进去。这就是均值填补的直觉——用一列已观测值的平均水平去顶替空缺。对数值型特征,常用均值或中位数:均值对异常值敏感,中位数更稳健——比如收入列被几个富豪拉高时,中位数才代表普通人。对分类型特征,则用众数填补,也就是“出现次数最多的类别”,相当于“大家都选它,空了也选它”。在 sklearn 里,SimpleImputer 一行就能搞定,strategy 参数设为 'mean'、'median' 或 'most_frequent' 即可。
简单填补有隐蔽的副作用:它把所有缺失值都填成同一个数,等于把分布的“尾巴”剪掉,压缩方差,让分布“变瘦”;更麻烦的是,补进去的值跟其他特征没有任何联动,会削弱特征间的相关关系。缺失率低时应急尚可,缺失多或后续要做因果分析就必须慎重。万能调味料能救急,但全桌菜都是一个味儿——老张知道,真要还原糖醋排骨的风味,得去看看“做法最接近的菜”是怎么用糖的。
- 待填补值带上帽子的 x 表示“估计出来的值”,而不是真实观测值。
- 均值记号x̄_j 是第 j 列的平均值,右边把它的计算过程展开了。
- 求和累加把第 j 列所有没缺失的观测值逐个相加,下标 t 从 1 数到 n_j。
- 除以个数用总和除以已观测个数,得到“代表性数值”填进空格。
KNN插补
老张灵光一现:糖醋排骨缺糖?去问问厨房里做法最像的几道菜——比如同属酸甜口的菠萝咕咾肉、鱼香肉丝——它们用了多少糖,再按接近程度加权折算过来。这就是 KNN(K 近邻)插补的思想:找最相似的样本,借它们的值来补。
KNN 插补的具体做法是:对每个含缺失值的样本,先找到与它最相似的 K 个完整样本,再用这些邻居在缺失列上的数值做加权平均,作为填补值。这里的“相似”靠距离度量,数值特征常用欧氏距离或曼哈顿距离。一个细节:如果目标样本的其他列也有缺失,距离计算要限定在“两边都齐”的维度上,不能拿缺失当 0 去算。sklearn 的 KNNImputer 实现了这一逻辑,n_neighbors 参数控制 K。
K 怎么选?太小容易被单个邻居的噪声带偏,太大又把相距甚远的样本也拉进来搅局,一般用交叉验证在 3~10 之间挑。KNN 插补不需要假设特征间的函数关系,擅长捕捉局部模式,但数据量大时计算距离的开销不低。借邻居的料比万能调味料讲究多了——酸甜口的菜之间确实有套路,老张看着邻居菜的用量,心里有了底。
- 邻居的值y_k 表示第 k 个近邻在缺失那一列上的真实观测值,它们是待加权平均的“素材”。
- 距离度量d_k 表示缺失样本与第 k 个邻居在完整维度上的距离,距离越小说明两道菜做法越像。
- 权重设计权重取距离倒数,再加一个极小正数 ε 防止分母为 0。
- 加权平均分子是权重乘以邻居值再求和,分母是权重之和,二者相除得到最终估值。
回归插补
更进一步,老张把全厨房的菜谱都翻出来,发现糖的用量其实和醋、酱油、料酒的用量存在稳定的数量关系。他让最会配比的老师傅总结出一条“公式”,再用这条公式去推算缺糖的菜。这就是回归插补:把特征间的关系变成定量方程,用方程补空缺。
回归插补的流程很清晰:把缺失列当作目标变量,其他完整列当作特征,用完整样本训练一个回归模型(线性回归、随机森林都可以),然后对缺失样本做预测,把预测值填进空格。它利用的是整个数据集里特征间的全局关系,比 KNN 的“局部相似”更有全局观,推理速度也更快。sklearn 的 IterativeImputer 可以把这种思路推广到多列循环插补。
回归插补有个隐患:预测值全部落在回归线上,方差被压缩,模型会“过度自信”。改进手法是加入随机扰动——预测值加上一个服从残差分布的随机项;更稳健的是 PMM(预测均值匹配),在预测值附近找一个真实观测值来替换,既保留相关性又保住分布形状。和 KNN 相比:KNN 擅长局部非线性模式,回归更擅长刻画全局线性趋势。老师傅的公式给了一个精确数字,但老张明白:配方是死的,火候是活的——给预测值加点“手抖”的随机扰动,补出来的菜才不至于千篇一律。
- 目标变量把缺失的那一列当作“被预测的菜”,其他列当作“已知配料”。
- 截距项β₀ 是回归线的截距,代表其他配料都为零时糖的基础用量。
- 特征加权和对每个非缺失列 c,取值 x_ic 乘上系数 β_c 后全部加起来,β_c 反映了该列对缺糖量的贡献大小。
多重插补
最讲究的做法,是老张请来 m 位经验不同的老师傅,每人独立地把整张菜谱补全一遍,做出 m 桌“模拟菜”。最后统计所有师傅在糖醋排骨这道菜上给出的糖量,取均值作为最终答案,同时留意师傅们意见的分歧——分歧本身就是不确定性。这就是多重插补(Multiple Imputation)。
标准流程叫 MICE(链式方程多重插补):第一步,对每个含缺失的列,用一个插补模型(回归、KNN、贝叶斯岭都可以)在链式迭代中互相预测,生成 m 份完整数据集;第二步,对每份数据分别做下游分析,比如训练模型或计算统计量;第三步,用 Rubin 法则把 m 个结果合并成最终的估计和方差。Python 里 statsmodels 的 MICE、fancyimpute、miceforest 都有实现。
多重插补的优点:既给出点估计,又通过方差合成量化了“补得有多没把握”,标准误更可信。代价是计算量大、实现复杂、参数多,不适合大规模数据上的快速迭代。它适合缺失机制为 MAR、缺失比例较高、且后续要做统计推断的场景。m 位师傅比一位老师傅可靠——分歧大时,老张就知道这道菜“补得没把握”,宁可用保守配方。多重插补贵,但买的是放心。
- m 份插补集先生成 m 份完整数据集,第 t 份用 D^(t) 表示,它们彼此独立。
- 每份的估计对第 t 份数据做下游分析,得到一个估计量 Q^(t),比如回归系数或均值。
- 取平均合并把所有估计量加起来除以 m,得到最终的合并估计。
实战选型
距离开饭只剩两小时。老张把经验整理成一张决策表:缺料不到 5% 且纯属意外——直接划掉;缺料三五成但有规律——参考相似菜谱(KNN);缺的是主料且做法有固定配比——用老师傅公式(回归);缺料多、客人又讲究、还想知道把握多大——请 m 位师傅(多重插补)。选择方法,本质是在“省事、保真、求稳”之间找平衡。
落到实践,选型要过四道关。第一关看缺失机制:MCAR 可删可简单填;MAR 适合 KNN、回归、多重插补;MNAR 必须结合业务知识。第二关看缺失比例:<5% 删行或均值;5%~20% 用 KNN 或回归;>20% 考虑多重插补,或评估是否直接删列。第三关看变量类型:数值特征用均值、中位数、KNN、回归;分类特征用众数或按类别比例插补。第四关看下游任务:纯预测可以粗补,统计推断建议多重插补。
工具有三档:入门用 sklearn 的 SimpleImputer、KNNImputer、IterativeImputer;进阶用 fancyimpute;研究向用统计包(R 的 mice、statsmodels 的 MICE)。插补完成后要留一手验证:对比插补前后的分布是否合理;故意遮掉一些真实值当测试集,看插补能不能猜准;检查是否引入异常值。老张最后拍板:冷门菜划掉,硬菜用 KNN,招牌菜请三位师傅多重插补。一桌年夜饭准时开席——数据清洗这件事,从来不是“最贵的最好”,而是“合适的最好”。
AI 应用场景
医疗电子病历补全
阶段:数据预处理 / 特征工程
解决的问题:病历中的身高、体重、血压、实验室指标常因护士漏录、设备故障而缺失。直接删除整行会丢掉大量诊断信息;乱填则会误导疾病风险评估。用 KNN 插补按年龄、性别、主诊断等特征寻找相似患者,用他们的指标估计缺失值,再配合多重插补评估不确定性。
具体案例:某三甲医院构建糖尿病并发症预测模型时,1.2 万份病历里 18% 存在至少一个指标缺失。团队先用 MICE 生成 10 份插补数据集,分别训练模型后用 Rubin 法则合并预测概率,模型 AUC 比“均值填补”方案提升了约 4 个百分点,且预测区间更可信。
银行信贷风控补录收入
阶段:特征工程与建模
解决的问题:信贷申请表中“月收入”缺失率常达 10%~25%,且高收入者更不愿填写,属于 MNAR 与 MAR 的混合。直接删除会丢掉申请人的其他信用特征;均值填补会严重低估收入方差,影响额度测算。采用“回归插补 + 随机扰动”并保留缺失指示变量,让模型自己学习“不愿填收入”这个行为信号。
具体案例:某消费金融公司用梯度提升树做违约预测,对收入缺失样本使用 PMM 插补,并在特征中加入 is_income_missing 标识,模型 KS 值从 0.38 提升到 0.43,同时避免了均值填补导致的收入分布坍缩。
用户画像与问卷清洗
阶段:数据采集后处理
解决的问题:用户注册时年龄、性别常留空,问卷里的“月消费额”因隐私顾虑缺失。数据量上千万级时,KNN 全量算距离不现实。实用策略是组合拳:先评估高缺失列的价值,性别用众数兜底,消费额用回归插补,最后用抽样验证插补质量。
具体案例:某电商平台做用户分群时,约 30% 用户缺少“月消费额”。团队先按是否填写拆成两个子群对比分布,发现填写者消费显著更高,于是对缺失单独建模,避免插补掩盖“沉默用户”的真实行为模式。
Python 演示
import numpy as np def mean_impute(X): """用每列均值填补缺失值(万能调味料方案)""" X = X.astype(float).copy() for j in range(X.shape[1]): col = X[:, j] mask = np.isnan(col) if mask.any(): col[mask] = np.nanmean(col) X[:, j] = col return X def knn_impute(X, k=3): """用 K 个最近完整样本的加权平均填补缺失值(借邻居的料)""" X = X.astype(float).copy() n_rows, n_cols = X.shape complete = [r for r in range(n_rows) if not np.isnan(X[r]).any()] for i in range(n_rows): row = X[i] if not np.isnan(row).any(): continue known = [c for c in range(n_cols) if not np.isnan(row[c])] for j in range(n_cols): if not np.isnan(row[j]): continue if not known or len(complete) < 1: X[i, j] = np.nanmean(X[:, j]) continue diff = X[np.ix_(complete, known)] - row[known] dists = np.sum(diff ** 2, axis=1) top = np.argsort(dists)[:k] weights = 1.0 / (dists[top] + 1e-8) X[i, j] = np.sum(weights * X[complete, j][top]) / np.sum(weights) return X if __name__ == "__main__": rng = np.random.RandomState(42) X_true = rng.rand(30, 3) X_miss = X_true.copy() mask = rng.rand(*X_true.shape) < 0.2 X_miss[mask] = np.nan print("缺失比例:", round(np.isnan(X_miss).mean(), 3)) X_mean = mean_impute(X_miss) X_knn = knn_impute(X_miss, k=3) mse_mean = np.mean((X_mean - X_true) ** 2) mse_knn = np.mean((X_knn - X_true) ** 2) print("均值填补 MSE:", round(mse_mean, 4)) print("KNN 插补 MSE:", round(mse_knn, 4)) print("结论: KNN 插补利用了特征间关系, 误差更小")
mask = rng.rand(*X_true.shape) < 0.2随机生成约两成的缺失位置,对应 MCAR 机制。np.isnan(col)找出这一列里所有空缺的格子,只补缺的地方。col[mask] = np.nanmean(col)用该列已观测值的均值填进所有空格,是均值填补的核心一行。complete = [r for r in range(n_rows) if not np.isnan(X[r]).any()]先筛出“完全没缺”的样本作为邻居池,保证距离可算。known = [c for c in range(n_cols) if not np.isnan(row[c])]确定目标样本哪些维度已知,距离只在已知维度上量。diff = X[np.ix_(complete, known)] - row[known]邻居池与目标样本在已知列上的差值矩阵。top = np.argsort(dists)[:k]挑距离最小的 K 个邻居的索引。weights = 1.0 / (dists[top] + 1e-8)距离越近权重越大,这就是“加权平均”里的“加权”。X[i, j] = np.sum(weights * X[complete, j][top]) / np.sum(weights)按权重合成邻居取值,填入空格。
常见误区
误区数据里有缺失值,直接把包含缺失的行删掉不就行了?删完数据干干净净,建模也不会报错,这是最稳妥的默认做法。
正解删除只有在缺失比例低(<5%)且机制为 MCAR 时才损失较小。若缺失是 MAR 或 MNAR,删除会系统性丢掉“不填的人”,引入选择偏差。好比把缺料的菜整道划掉,客人爱吃的菜没了,菜单就再也代表不了客人的真实口味。
为何常见:删除操作最简单直观,而且很多入门教程的第一反应就是“清洗”,小白容易把删除当成默认动作。
误区平均值是数据最典型的代表,用均值填空缺肯定没错,而且复杂度最低,是所有方法里最稳妥的兜底方案。
正解均值填补会压缩方差、削平分布,还会让补进去的值与其他特征“零关联”,破坏变量间的相关结构。缺失率一高,模型会严重低估不确定性。它适合低缺失率下的应急,而不是“最安全”的默认选项。
为何常见:日常生活中“取平均”就是衡量典型水平的常规操作,这个直觉被顺理成章地迁移到了数据处理里。
误区KNN 插补就是找 K 个最近的样本,把它们的值加起来除以 K 就完事了,跟投票一样一人一票。
正解标准的 KNN 插补是距离加权平均——越近的邻居贡献越大,权重通常是距离的倒数。如果直接算术平均,远处邻居和近邻一视同仁,插补精度会明显下降。此外,距离计算还要避开两边都缺失的维度,不能把缺的值当成 0 去算。
为何常见:分类场景里的 KNN 是“少数服从多数”的平权投票,初学者容易把分类的投票逻辑平移到插补的加权逻辑上。
误区多重插补只是把插补流程多跑几遍,最后求个平均值,本质上跟填一次没区别,纯属增加计算量。
正解多重插补的核心价值不在平均值,而在方差合成——它用“组间差异 + 组内差异”来量化“我们有多不确定这个补出来的值”,从而给出更诚实的标准误和置信区间。取平均只是 Rubin 法则的一半,另一半才是它的灵魂。
为何常见:只盯着合并公式里的均值部分,忽略了背后的方差合成,自然以为它只是“重复的均值填补”。
误区只要把缺失值都用算法补上了,数据集就完美了,后面直接跑模型就行,没必要再回头看插补效果。
正解插补是有假设的(尤其假设 MAR),补完必须验证:对比插补前后分布是否合理、故意藏起一些真实值评估插补误差、检查是否引入异常值。就像老张补完菜谱要先试菜,不能只看纸面数字。
为何常见:数据清洗流程的“终点感”让人放松警惕,忽视了插补本身也是一个需要评估的建模步骤。
面试题
Q1. 下列哪种情况属于完全随机缺失(MCAR)?
- A.收入越高的人越不愿填收入
- B.纸张破损导致部分问卷数据丢失← 正确答案
- C.女性更倾向不填身高数据
- D.疾病患者漏填某项指标
答案:B。MCAR 指缺失与任何数据都无关。纸张破损是纯粹意外,符合 MCAR。A、C、D 的缺失都和样本自身属性有关,分别属于 MNAR 或 MAR。
Q2. 对分类特征的缺失值,最常用的简单填补法是?
- A.均值填补
- B.中位数填补
- C.众数填补← 正确答案
- D.回归插补
答案:C。分类特征没有“平均”的概念,均值和中位数只适用于数值特征。众数(出现最多的类别)是分类变量的合理“代表”,回归插补则属于更复杂的模型方法。
Q3. KNN 插补与均值填补相比,主要优势是?
- A.实现代码更简单
- B.利用特征间的关系信息← 正确答案
- C.运行速度更快
- D.不依赖距离计算
答案:B。均值填补只用了单列的集中趋势,KNN 插补通过距离度量借用了其他特征的信息,补出来的值能和整体模式吻合。代码和速度方面 KNN 反而更复杂、更慢。
Q4. 均值填补的主要缺陷是?
- A.计算开销过高
- B.低估方差削弱相关← 正确答案
- C.无法处理数值数据
- D.只能用于小样本
答案:B。均值填补把所有空缺填成同一个数,尾巴被剪掉,方差被压缩;补进去的值与其他特征零联动,破坏了相关结构。它的计算开销很低,且本来就是给数值数据用的。
Q5. 关于 KNN 插补,下列说法正确的有?
- A.依据样本间距离寻找近邻← 正确答案
- B.邻居贡献按距离加权← 正确答案
- C.K 值越大插补一定越好
- D.距离计算需避开缺失维度← 正确答案
答案:ABD。KNN 插补用距离找邻居、按距离倒数加权平均,距离只能在两边都完整的维度上计算。K 值并非越大越好,太大把远样本也拉进来,会过度平滑。
Q6. 下列哪种缺失机制最难处理?
- A.完全随机缺失(MCAR)
- B.随机缺失(MAR)
- C.非随机缺失(MNAR)← 正确答案
- D.三种机制难度相同
答案:C。MNAR 的缺失与缺失值本身有关,数据里没有直接线索,必须靠领域知识或专门建模。MCAR 最友好,MAR 是主流插补方法能覆盖的范围。
Q7. 多重插补(MICE)的特点包括?
- A.多次生成完整数据集← 正确答案
- B.能反映插补的不确定性← 正确答案
- C.用 Rubin 法则合并估计← 正确答案
- D.不需要任何模型假设
答案:ABC。MICE 生成 m 份插补集、分别分析后用 Rubin 法则合并,方差合成体现了不确定性。但它依赖插补模型和缺失机制的假设,并非“零假设”。
Q8. 缺失率 5% 且为 MCAR 时,下列做法最合理的是?
- A.直接删除缺失行← 正确答案
- B.用众数填补所有特征
- C.必须用多重插补
- D.不做任何处理直接建模
答案:A。MCAR 且缺失率低时,删除行的信息损失可忽略,是最简洁的选择。众数填补对数值特征不合适,多重插补在此场景属于过度设计,不做处理则多数模型报错。
Q9. 回归插补中,为减少插补值方差被低估,通常的做法是?
- A.增大回归模型复杂度
- B.加入随机扰动项← 正确答案
- C.删除所有缺失样本
- D.使用更大的数据集
答案:B。预测值全落在回归线上会压缩方差。加入服从残差分布的随机扰动,或使用 PMM 匹配真实观测值,能恢复分布形状。模型复杂度和数据量不能解决“过度自信”问题。
Q10. 下列属于 MNAR 场景的有?
- A.血压计损坏导致测量值缺失
- B.体重过重者拒绝填体重← 正确答案
- C.高收入人群漏报收入← 正确答案
- D.问卷印刷错误导致整页丢失
答案:BC。B、C 的缺失都与缺失值本身有关——体重、收入越高越不愿填,属于 MNAR。A、D 是设备故障和印刷意外,与数据值无关,属于 MCAR。