上一篇文章(缺失值处理)介绍了缺失值处理的判断方法,这一讲接着介绍缺失值常用的几种处理方法:删除法,替换法和插补法。不同的方法对应不同类型的缺失值。
1.删除法
如果缺失值的比例很小,且不影响整体的数据结构,即缺失值类型是完全随机缺失时,可以考虑将缺失值删除,该方法操作非常简单,使用函数na.omit()就可以将含有缺失值的行删除。其函数的基本书写格式为:
代码语言:javascript复制na .omit (object,....)
其中object即为需要处理的数据对象。下面我们对algae数据集进行处理:
代码语言:javascript复制> algae=na.omit(algae)
> sum(is.na(algae))
[1] 0
上一篇文章中,我们介绍到该数据集有33个缺失值,删除后,现在为0了。
除了na.omit()函数外,还可以利用complete.cases函数来删除含有缺失值的行。
代码语言:javascript复制> # 因为上一句代码已经删除过,这里重新加载原始数据
> data(algae)
> algae<-algae[complete.cases(algae),]
> sum(!complete.cases(algae))
[1] 0
2.替换法
直接删除含有缺失值的行记录的代价和风险较大,故我们可以考虑将缺失值部分替换掉,如用均值去替换,即均值替换法,该方法根据变量的不同类型选择不同的替换,对数值型变量采用均值替换,对非数值型变量采用众数替换。
下面我们将对algae数据集采用均值替换处理缺失值:
代码语言:javascript复制> data(algae)
> mean(complete.cases(algae))
[1] 0.92
> algae[is.na(algae)]<-mean(complete.cases(algae))
> sum(!complete.cases(algae))
[1] 0
但是均值替换法还是存在一些问题,因为该方法适用于处理完全随机缺失数据,且会改变整体数据的统计性质,比如方差变小,存在偏差等,因此在在实践中并不常用。
3.插补法
实战中常用的方法是插补法,随机插补的思想类似,利用非缺失数据的均值或者随机数来填补缺失值,下面我们详细介绍多重插补。
多重插补的主要思想是:利用蒙特卡洛模拟法(MCMC)将原始数据集插补成几个完整数据集,在每个新数据集中利用线性回归(lm)或广义线性回归(glm)等方法进行插补建模,再将这些完整的模型整合到一起,评价插补模型的优劣并返回完数据集。
该方法主要利用mice包中的函数mice进行,其函数的基本书写格式为,
代码语言:javascript复制mice(data,m=5,method=vector("character",length =ncol (data)),seed = NA,
defaultMethod = c("pmm","logreg","polyreg","polr"),....)
参数介绍:
data一个包含完整数据和缺失数据的矩阵或数据框,其中各缺失数据用符号NA表示;
m:指定的多正插补数,默认值为5;
method:一个字符串,或者长度与数据集列数相同的字符串向量,用于指定数据集中的每一列采用的插补方法,单一字符串指定所有列用相同方法插补,字符串向量指定不同列采用不同方法插补,默认插补法取决需要插补的目标列,并由defaulmethod指定参数;
seed:一个整数,用于函数set.seed()的参数,指定产生固定的随机数的个数,默认值为NA;
defaultMethod:一个向量,用于指定每个数据集采用的插补建模方法,可供选者的方法有多种,“pmm”表示用预测的均值匹配,“logreg”表示用逻批回归拟合,“polyreg”表示多项式拟合,“polr”表示采用比例优势模型拟合等。
需要注意的是:选择不同的插补建模方法对数据有不同的要求,回归法适用于数值型数据集,“pmm”对数据格式没有特殊要求。在实战过程中我们还会用到函数pool()、函数compute()等。下面我们将用到一些回归知识, 有疑感的话先放着,后面分析数据时我们会深入了解。
代码语言:javascript复制> imp<-mice(algae[,4:11],seed=1234)
iter imp variable
1 1
1 2
1 3
1 4
1 5
2 1
2 2
2 3
2 4
2 5
3 1
3 2
3 3
3 4
3 5
4 1
4 2
4 3
4 4
4 5
5 1
5 2
5 3
5 4
5 5
> fit <- with(imp,lm(mxPH~.,data = algae[,4:11]))
> pool=pool(fit)
> options(digits=3) # 设定输出结果保留3位小数。
> summary(pool)
estimate std.error statistic df p.value
(Intercept) 7.90e 00 2.49e-01 31.735 190 0.00e 00
mnO2 -1.43e-02 2.39e-02 -0.598 190 5.51e-01
Cl 2.20e-03 1.32e-03 1.669 190 9.68e-02
NO3 -2.15e-02 2.18e-02 -0.986 190 3.25e-01
NH4 -1.75e-05 4.08e-05 -0.429 190 6.69e-01
oPO4 1.36e-03 1.50e-03 0.908 190 3.65e-01
PO4 -5.96e-04 1.14e-03 -0.522 190 6.02e-01
Chla 1.31e-02 2.82e-03 4.654 190 6.10e-06
上述代码表示:
首先创建一个imp对象,该对象是包含4个插补对象的列表,使用的数据为algae数据集中含有缺失值的第4到11列数据,默认插补查补数据集为5个;然后创建fit对象,用于设定统计分析方法,这里指定线性回归,则fit是一个包含4个统计分析结果的列表对象;再创建pool 对象,该对象将前面的四个统计分析结果汇总;最后用summary函数显示pool的统计信息,指定输出结果保留3位小数。
插补完后,对插补数据和原始数据进行对比,利用mice包中的函数stripplot()对变量分布图进行可视化。
代码语言:javascript复制algae_complete=complete(imp,action=1)
sum(is.na(algae_complete))
par(mfrow=c(3,3))
stripplot(imp,pch=c(1,8),col=c("grey","1"))
par(mfrow=c(1,1)
缺失值处理是一个不容易的工程,我们在数据挖掘中可选择对缺失数据不敏感的方法,比如决策树,这样就省略了缺失值处理的步骤。如果对于数据敏感的方法,还是要处理的哦!!