一、处理缺失值的步骤
一个完整的处理方法通常包含以下几个步骤:
- 识别缺失数据
- 检查导致数据缺失的原因
- 删除包含缺失值的实例或用合理的数值代替(插补)缺失值
遗憾的是,往往只有识别缺失数据是清晰明确的步骤。明白数据为何缺失依赖于你对数据生成过程的理解,而决定如何处理缺失值则需要判断那种方法的结果最为可靠和精确。
缺失数据的分类:统计学家通常将数据分为三类。尽管它们都采用概率术语进行描述,但思想都非常直观。
- 完全随机缺失(MCAR)。若某变量的缺失数据与其他任何观测变量或未观测变量都不相关,则数据为完全随机缺失。注意,如果每个有缺失值的变量都是MACR,那么可以将数据完整的实例看作对更大数据集的一个简单随机抽样。
- 随机缺失(MAR)。若某变量上的缺失数据与其他观测变量相关,与它自己的未观测值不相关,则数据为随机缺失。
- 非随机缺失(NMAR)。若缺失数据不属于MCAR和MAR,则数据为非随机缺失(NMAR)。
二、识别缺失值
R使用NA代表缺失值,NaN代表不可能值,符号Inf和-Inf分别代表正无穷和负无穷。函数is.na()、is.nan()、和is.infinite()可分别用来识别缺失值、不可能值和无穷值。每个返回结果都是TRUE或FALSE。
由于逻辑值TRUE和FALSE分别等价于数值1和0,可用sum()和mean()函数来获取关于缺失数据的有用信息。
> sum(is.na(sleep$Dream))
[1] 12
> mean(is.na(sleep$Dream))
[1] 0.19
> mean(!complete.cases(sleep))
[1] 0.32
结果表明变量Dream有12个缺失值,19%的实例在此变量上有缺失值。另外,数据集中32%的实例包含一个或多个缺失值。
对于识别确实值需要牢记两点。第一,complete.cases()函数仅将NA和NaN识别为缺失值,无穷值(Inf和-Inf)被当作有效值。第二,必须使用与本文以上提到的类似函数来识别R数据对象中的缺失值。像myvar == NA 这样的逻辑比较无法实现。
三、探索缺失值模式
知道数据为何缺失,这将为后续深入研究提供许多启示。
- 列表显示缺失值
mice包中的md.pattern()函数可生成一个以矩阵或数据框形式展示缺失值模式的表格。将函数应用到sleep数据集,可得到:
> library(mice) > md.pattern(sleep) BodyWgt BrainWgt Pred Exp Danger Sleep Span Gest Dream NonD 42 1 1 1 1 1 1 1 1 1 1 0 2 1 1 1 1 1 1 0 1 1 1 1 3 1 1 1 1 1 1 1 0 1 1 1 9 1 1 1 1 1 1 1 1 0 0 2 2 1 1 1 1 1 0 1 1 1 0 2 1 1 1 1 1 1 1 0 0 1 1 2 2 1 1 1 1 1 0 1 1 0 0 3 1 1 1 1 1 1 1 0 1 0 0 3 0 0 0 0 0 4 4 4 12 14 38
0表示缺失值,1表示非缺失值。每行表示一个可能的缺失值模式,左边第一个数给出了该模式的数量,右边第一个数给出了该模式有几个缺失值,例如完整数据有42个,有2个观测的Span缺失,有1个观测同时缺失Span、Dream和NonD。最后一行给出了每个变量缺失值出现的次数,如Sleep变量共有4个缺失值,数据集一共有38个缺失值。
- 图形探索缺失数据
library("VIM") aggr(sleep, prop=FALSE, numbers=TRUE)