有的时候,面对一个有缺失值的数据,我只想赶紧把它插补好,此时的我并不在乎它到底是怎么缺失、插补质量如何等,我只想赶紧搞定缺失值,这样好继续进行接下来的工作。
今天这篇推文就是为这种情况准备的!
之前介绍过一个非常好用的缺失值插补R包:R语言缺失值插补之simputation包,支持管道符,使用起来非常简单且优雅,而且支持的方法的也非常多。但是它有一个最大的问题,不能一次性填补整个数据集的缺失值。
比如我有一个数据集,我知道它有缺失值,但是不知道在哪些列,但是我只想快速填补所有的缺失值,这时候这个R包就点力不从心了。
关于R语言中的缺失值插补,大家遇到最多的教程应该是mice
包,不过我不太常用,所以就不介绍了。
一般来说,如果只是简单的均值或中位数填补的话,不需要R包,自己写一行简单的代码就搞定了。
均值/中位数/最大值/最小值等
新建一个有缺失值的数据集。
代码语言:javascript复制set.seed(12)
df <- data.frame(a = sample(c(NA,NA,1:5),10, replace = T),
b = sample(c(NA,NA,1:10),10, replace = T),
c = sample(c(NA,1:5),10, replace = T),
d = sample(c(NA,1:3),10, replace = T)
)
df
## a b c d
## 1 NA NA NA 1
## 2 NA NA 1 2
## 3 5 7 2 1
## 4 1 4 5 2
## 5 4 10 4 1
## 6 3 8 5 3
## 7 3 8 3 3
## 8 2 5 4 3
## 9 NA 6 4 3
## 10 1 2 NA 2
现在这个数据集有7个缺失值,我不想知道这些缺失值的具体情况,只想立马把它们填补好,不然没法进行下一步操作!
代码语言:javascript复制table(is.na(df))
##
## FALSE TRUE
## 33 7
均值插补:
代码语言:javascript复制# 用每一列的均值插补
df1 <- sapply(df, function(x){
x[is.na(x)] <- mean(x, na.rm=T)
x
})
df1
## a b c d
## [1,] 2.714286 6.25 3.5 1
## [2,] 2.714286 6.25 1.0 2
## [3,] 5.000000 7.00 2.0 1
## [4,] 1.000000 4.00 5.0 2
## [5,] 4.000000 10.00 4.0 1
## [6,] 3.000000 8.00 5.0 3
## [7,] 3.000000 8.00 3.0 3
## [8,] 2.000000 5.00 4.0 3
## [9,] 2.714286 6.00 4.0 3
## [10,] 1.000000 2.00 3.5 2
table(is.na(df1))
##
## FALSE
## 40
中位数插补:
代码语言:javascript复制# 用每一列的中位数插补
df2 <- sapply(df, function(x){
x[is.na(x)] <- median(x, na.rm=T)
x
})
table(is.na(df2))
##
## FALSE
## 40
像这种比较简单的插补方法,比如均数、中位数、最大值,最小值等方法,也可以通过Hmisc
包实现。
library(Hmisc)
impute(df$a, fun = mean) # median, max, min
## 1 2 3 4 5 6 7 8
## 2.714286* 2.714286* 5.000000 1.000000 4.000000 3.000000 3.000000 2.000000
## 9 10
## 2.714286* 1.000000
不过也是一列一列的进行插补,如果同时有多列都有缺失值,也要配合其他函数完成。
代码语言:javascript复制# 支持用常数插补!
impute(df$a, fun = 2)
## 1 2 3 4 5 6 7 8 9 10
## 2* 2* 5 1 4 3 3 2 2* 1
其他常见R包
最常见的比如KNN插补、随机森林插补等。
KNN插补可以通过impute
,这个包在bioconductor上,不在cran上;另外这个包不接受data.frame
格式,需要变成matrix
格式!
library(impute)
impute.knn(as.matrix(df))$data
## a b c d
## [1,] 0.000000 0.0 0.000000 1
## [2,] 2.111111 5.2 1.000000 2
## [3,] 5.000000 7.0 2.000000 1
## [4,] 1.000000 4.0 5.000000 2
## [5,] 4.000000 10.0 4.000000 1
## [6,] 3.000000 8.0 5.000000 3
## [7,] 3.000000 8.0 3.000000 3
## [8,] 2.000000 5.0 4.000000 3
## [9,] 2.111111 6.0 4.000000 3
## [10,] 1.000000 2.0 3.444444 2
还可以通过VIM
等包实现,支持data.frame
格式:
library(VIM)
kNN(df)[1:ncol(df)]
## a b c d
## 1 3 7 3 1
## 2 3 7 1 2
## 3 5 7 2 1
## 4 1 4 5 2
## 5 4 10 4 1
## 6 3 8 5 3
## 7 3 8 3 3
## 8 2 5 4 3
## 9 3 6 4 3
## 10 1 2 4 2
随机森林插补可以使用missForest
,使用起来也是非常简单方便:
library(missForest)
missForest(df)$ximp
## a b c d
## 1 3.68 8.418333 3.39 1
## 2 2.86 5.790667 1.00 2
## 3 5.00 7.000000 2.00 1
## 4 1.00 4.000000 5.00 2
## 5 4.00 10.000000 4.00 1
## 6 3.00 8.000000 5.00 3
## 7 3.00 8.000000 3.00 3
## 8 2.00 5.000000 4.00 3
## 9 2.28 6.000000 4.00 3
## 10 1.00 2.000000 4.15 2
以上就是我常用的缺失值插补R包,除此之外,做机器学习的专用包caret/mlr3/tidymodels
等,也包含很多缺失值处理的方法,还有tidyverse
也有缺失值处理的函数,大家可以自行探索。
此外,缺失值插补在cran
的task view
里面有一个专题:Missing Data
,大家感兴趣的可以自己查看,里面有R语言所有和缺失值插补有关的R包介绍!