R语言中有很多插补缺失值的R包,但是这些R包的使用语法都不一样,不利于学习和记忆。
simputation
包旨在简化缺失值插补的流程,提供了统一的使用语法,提供多种常见的插补缺失值的方法,可以和管道符%>%
连用,非常值得学习。
这个包和之前介绍的缺失值探索的R包naniar
搭配使用效果非常棒,包的作者也经常互相cue,一个用于探索,一个用于插补,而且是tidy
风格的,风格统一,非常推荐大家学习!
naniar
介绍:R语言缺失值探索的强大R包:naniar
simputation
这个包提供了很多了插补缺失值的方法,很多方法我也没有使用过,今天学习一下。目前支持以下插补方法:
- 基于模型的方法
- 线性回归
- 稳健线性回归
- 岭回归/弹性网络/lasso回归
- CART模型(决策树)
- 随机森林
- 多元插补
- 基于最大期望值的方法
- missForest
- Donor imputation (including various donor pool specifications)
- K最近邻法
- sequential hotdeck (LOCF, NOCB)
- random hotdeck
- Predictive mean matching
- 其他
- median imputation
- Proxy imputation: 使用其他列的值或使用简单的转换得到的值.
- Apply trained models for imputation purposes.
安装R包
代码语言:javascript复制install.packages('simputation')
此包需要很多依赖包,默认不会安装依赖包,可以通过以下代码全部安装:
代码语言:javascript复制install.packages('simputation', dependencies = T)
基本使用方法
代码语言:javascript复制impute_<model>(data, formula, [model-specific options])
model
是使用的方法,目前支持以下方法:
impute_rlm
: robust linear modelimpute_en
: ridge/elasticnet/lassoimpute_cart
: CARTimpute_rf
: random forestimpute_rhd
: random hot deckimpute_shd
: sequential hot deckimpute_knn
: k nearest neighboursimpute_mf
: missForestimpute_em
: mv-normalimpute_const
: 用一个固定值插补impute_lm
: linear regressionimpute_pmm
: Hot-deck imputationimpute_median
: 均值插补impute_proxy
: 自定义公式插补,可以用均值等
data
是需要插补的数据框,输出数据和输入数据结构一样,只不过缺失值被插补了。
formula
指定需要插补的列。
[model-specific options]
是根据所选模型不同有不同的参数。
示例
使用鸢尾花数据集,先把其中的一些值变为缺失值。
代码语言:javascript复制dat <- iris
dat[1:3, 1] <- dat[3:7, 2] <- dat[8:10, 5] <- NA
head(dat, 10)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 NA 3.5 1.4 0.2 setosa
## 2 NA 3.0 1.4 0.2 setosa
## 3 NA NA 1.3 0.2 setosa
## 4 4.6 NA 1.5 0.2 setosa
## 5 5.0 NA 1.4 0.2 setosa
## 6 5.4 NA 1.7 0.4 setosa
## 7 4.6 NA 1.4 0.3 setosa
## 8 5.0 3.4 1.5 0.2 <NA>
## 9 4.4 2.9 1.4 0.2 <NA>
## 10 4.9 3.1 1.5 0.1 <NA>
使用线性回归方法插补缺失值:
根据Sepal.Width
和Species
这两列,来预测Sepal.Length
这一列的缺失值:
library(simputation)
da1 <- impute_lm(dat, Sepal.Length ~ Sepal.Width Species)
head(da1, 10)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.076579 3.5 1.4 0.2 setosa
## 2 4.675654 3.0 1.4 0.2 setosa
## 3 NA NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
## 7 4.600000 NA 1.4 0.3 setosa
## 8 5.000000 3.4 1.5 0.2 <NA>
## 9 4.400000 2.9 1.4 0.2 <NA>
## 10 4.900000 3.1 1.5 0.1 <NA>
此处Sepal.Length
的第3个值还是NA
,这是因为Sepal.Width
这一列的第3个值是NA
导致的,线性回归不能插补这样的缺失值。
可以通过中位数进行插补:
代码语言:javascript复制da2 <- impute_median(da1, Sepal.Length ~ Species) # Species用来分组,相当于根据Species这一列分组求中位数然后分别插补
head(da2, 10)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.076579 3.5 1.4 0.2 setosa
## 2 4.675654 3.0 1.4 0.2 setosa
## 3 5.000000 NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
## 7 4.600000 NA 1.4 0.3 setosa
## 8 5.000000 3.4 1.5 0.2 <NA>
## 9 4.400000 2.9 1.4 0.2 <NA>
## 10 4.900000 3.1 1.5 0.1 <NA>
使用决策树方法来插补Species
这一列:
da3 <- impute_cart(da2, Species ~ .)
head(da3,10)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.076579 3.5 1.4 0.2 setosa
## 2 4.675654 3.0 1.4 0.2 setosa
## 3 5.000000 NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
## 7 4.600000 NA 1.4 0.3 setosa
## 8 5.000000 3.4 1.5 0.2 setosa
## 9 4.400000 2.9 1.4 0.2 setosa
## 10 4.900000 3.1 1.5 0.1 setosa
使用管道符连接多种插补方法
使用%>%
管道符连接一系列操作:
library(magrittr)
da4 <- dat %>%
impute_lm(Sepal.Length ~ Sepal.Width Species) %>%
impute_median(Sepal.Length ~ Species) %>%
impute_cart(Species ~ .)
head(da4,10)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.076579 3.5 1.4 0.2 setosa
## 2 4.675654 3.0 1.4 0.2 setosa
## 3 5.000000 NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
## 7 4.600000 NA 1.4 0.3 setosa
## 8 5.000000 3.4 1.5 0.2 setosa
## 9 4.400000 2.9 1.4 0.2 setosa
## 10 4.900000 3.1 1.5 0.1 setosa
使用一个固定值进行插补
原数据这样:
代码语言:javascript复制head(dat, 10)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 NA 3.5 1.4 0.2 setosa
## 2 NA 3.0 1.4 0.2 setosa
## 3 NA NA 1.3 0.2 setosa
## 4 4.6 NA 1.5 0.2 setosa
## 5 5.0 NA 1.4 0.2 setosa
## 6 5.4 NA 1.7 0.4 setosa
## 7 4.6 NA 1.4 0.3 setosa
## 8 5.0 3.4 1.5 0.2 <NA>
## 9 4.4 2.9 1.4 0.2 <NA>
## 10 4.9 3.1 1.5 0.1 <NA>
使用7插补:
代码语言:javascript复制da4 <- impute_const(dat, Sepal.Length ~ 7)
head(da4,10)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 7.0 3.5 1.4 0.2 setosa
## 2 7.0 3.0 1.4 0.2 setosa
## 3 7.0 NA 1.3 0.2 setosa
## 4 4.6 NA 1.5 0.2 setosa
## 5 5.0 NA 1.4 0.2 setosa
## 6 5.4 NA 1.7 0.4 setosa
## 7 4.6 NA 1.4 0.3 setosa
## 8 5.0 3.4 1.5 0.2 <NA>
## 9 4.4 2.9 1.4 0.2 <NA>
## 10 4.9 3.1 1.5 0.1 <NA>
复制另一列的值进行插补:
代码语言:javascript复制da4 <- impute_proxy(dat, Sepal.Length ~ Sepal.Width)
head(da4,10)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 3.5 3.5 1.4 0.2 setosa
## 2 3.0 3.0 1.4 0.2 setosa
## 3 NA NA 1.3 0.2 setosa
## 4 4.6 NA 1.5 0.2 setosa
## 5 5.0 NA 1.4 0.2 setosa
## 6 5.4 NA 1.7 0.4 setosa
## 7 4.6 NA 1.4 0.3 setosa
## 8 5.0 3.4 1.5 0.2 <NA>
## 9 4.4 2.9 1.4 0.2 <NA>
## 10 4.9 3.1 1.5 0.1 <NA>
对多列使用同一种插补方法
根据Petal.Length
和Species
这两列使用rlm
方法插补Sepal.Length
和Sepal.Width
:
da5 <- impute_rlm(dat, Sepal.Length Sepal.Width ~ Petal.Length Species)
head(da5)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 4.945416 3.500000 1.4 0.2 setosa
## 2 4.945416 3.000000 1.4 0.2 setosa
## 3 4.854056 3.378979 1.3 0.2 setosa
## 4 4.600000 3.440107 1.5 0.2 setosa
## 5 5.000000 3.409543 1.4 0.2 setosa
## 6 5.400000 3.501236 1.7 0.4 setosa
同样也支持tidyverse
中的.
和-
,以下代码使用均值加残差插补除了Species
的所有列:
da6 <- impute_lm(dat, . - Species ~ 0 Species, add_residual = "normal") # Species用来分组
head(da6)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 4.292233 3.500000 1.4 0.2 setosa
## 2 4.132790 3.000000 1.4 0.2 setosa
## 3 4.443134 3.643322 1.3 0.2 setosa
## 4 4.600000 3.518055 1.5 0.2 setosa
## 5 5.000000 3.355422 1.4 0.2 setosa
## 6 5.400000 3.094199 1.7 0.4 setosa
分组插补
可以在公式中使用|
指定组。
# 新建一个含缺失值的数据框
dat <- iris
dat[1:3,1] <- dat[3:7,2] <- NA
# 根据Species分组,然后再插补
da8 <- impute_lm(dat, Sepal.Length ~ Petal.Width | Species)
head(da8)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 4.968092 3.5 1.4 0.2 setosa
## 2 4.968092 3.0 1.4 0.2 setosa
## 3 4.968092 NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
如果指定了一个或多个分组变量(通过用 分隔多个变量来指定多个),函数内部会进行以下操作:
- 根据分组变量的值将数据划分为子集
- 估计每个数据子集的模型并进行插补
- 组合插补的子集
也可以和dplyr
包的group_by
连用:
library(magrittr)
library(dplyr)
##
## 载入程辑包:'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
dat <- iris
dat[1:3,1] <- dat[3:7,2] <- NA
dat %>% group_by(Species) %>%
impute_lm(Sepal.Length ~ Petal.Width)
## # A tibble: 150 x 5
## # Groups: Species [3]
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## * <dbl> <dbl> <dbl> <dbl> <fct>
## 1 4.96 3.5 1.4 0.2 setosa
## 2 4.96 3 1.4 0.2 setosa
## 3 4.96 NA 1.3 0.2 setosa
## 4 4.6 NA 1.5 0.2 setosa
## 5 5 NA 1.4 0.2 setosa
## 6 5.4 NA 1.7 0.4 setosa
## 7 4.6 NA 1.4 0.3 setosa
## 8 5 3.4 1.5 0.2 setosa
## 9 4.4 2.9 1.4 0.2 setosa
## 10 4.9 3.1 1.5 0.1 setosa
## # ... with 140 more rows
使用impute_proxy
指定自己的插补方法
impute_proxy
允许自定义formula
自定义一个robust ratio imputation
方法进行插补:
dat <- iris
dat[1:3,1] <- dat[3:7,2] <- NA
dat <- impute_proxy(dat, Sepal.Length ~ median(Sepal.Length,na.rm=TRUE)/median(Sepal.Width, na.rm=TRUE) * Sepal.Width | Species)
head(dat)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.147059 3.5 1.4 0.2 setosa
## 2 4.411765 3.0 1.4 0.2 setosa
## 3 NA NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
自定义使用均值进行插补:
代码语言:javascript复制dat <- iris
dat[1:3,1] <- dat[3:7,2] <- NA
dat <- impute_proxy(dat, Sepal.Length ~ mean(Sepal.Length,na.rm=TRUE))
head(dat)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.862585 3.5 1.4 0.2 setosa
## 2 5.862585 3.0 1.4 0.2 setosa
## 3 5.862585 NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
自定义使用均值进行插补(先根据Species
分组再计算均值):
dat <- iris
dat[1:3,1] <- dat[3:7,2] <- NA
dat <- impute_proxy(dat, Sepal.Length ~ mean(Sepal.Length,na.rm=TRUE) | Species)
head(dat)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.012766 3.5 1.4 0.2 setosa
## 2 5.012766 3.0 1.4 0.2 setosa
## 3 5.012766 NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
使用在其他数据集中训练过的模型插补数据
在其他数据集训练模型
代码语言:javascript复制m <- lm(Sepal.Length ~ Sepal.Width Species, data = iris)
新建一个要插补的数据集
代码语言:javascript复制dat <- iris
dat[1:3,1] <- dat[3:7,2] <- NA
head(dat)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 NA 3.5 1.4 0.2 setosa
## 2 NA 3.0 1.4 0.2 setosa
## 3 NA NA 1.3 0.2 setosa
## 4 4.6 NA 1.5 0.2 setosa
## 5 5.0 NA 1.4 0.2 setosa
## 6 5.4 NA 1.7 0.4 setosa
使用训练过的模型进行插补
代码语言:javascript复制dat <- impute(dat, Sepal.Length ~ m)
head(dat)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.063856 3.5 1.4 0.2 setosa
## 2 4.662076 3.0 1.4 0.2 setosa
## 3 NA NA 1.3 0.2 setosa
## 4 4.600000 NA 1.5 0.2 setosa
## 5 5.000000 NA 1.4 0.2 setosa
## 6 5.400000 NA 1.7 0.4 setosa
以上就是今天的主要内容,关于缺失值的探索和处理还有很多其他优秀的R包,将在以后继续为大家介绍其他工具。但是风格最统一、搭配最好的就是这两个包了!