继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

利用R进行脏数据清洗

牛魔王的故事
关注TA
已关注
手记 196
粉丝 111
获赞 628

  在进行正式的数据分析之前,必须要保证数据的质量,故而我们要处理缺失值、异常值这些脏数据。本篇博客参照了如何使用R语言解决可恶的脏数据一文,进行了模拟脏数据清洗。

 一、缺失值

      缺失值的处理要依据数据的类型和其内容进行相应处理,常用的方法有行删除、众数替代、均值替代以及多重插补法等等。 

      以下举个例子:

#生成1000条无缺失值数据
> set.seed(1234)
> Tel <- 15021888000:15021888999
> Sex <- sample(c('F','M'), size = 1000, replace = T, prob = c(0.45,0.55))
> Age <- round(runif(n = 1000, min = 16, max = 60))
> Freq <- round(runif(n = 1000, min = 1, max = 368))
> Amount <- rnorm(n = 1000, mean = 134, sd = 10)
> ATV <- runif(n = 1000, min = 23, max = 138)
> df <- data.frame(Tel = Tel, Sex = Sex, Age = Age, Freq = Freq, Amount = Amount, ATV = ATV)

      通过summary(df)得到df简单描述统计如下:

#随机产生100个缺失值
> #随机参数某行某列的下标
> set.seed(1234)
> i <- sample(1:6, size = 100, replace = T)
> j <- sample(1:1000, size = 100)
> #将下标组合成矩阵
> index <- as.matrix(data.frame(j,i))
> #将原始数据框转换为矩阵
> df <- as.matrix(df)
> #将随机参数的行列赋值为NA
> df[index] <- NA
> #重新将矩阵转换为数据框
> df2 <- as.data.frame(df)
> #变换变量类型
> df2$Age <- as.integer(df2$Age)
> df2$Freq <- as.integer(df2$Freq)
> df2$Amount <- as.numeric(df2$Amount)
> df2$ATV <- as.numeric(df2$ATV)

      再次通过summary()函数对df2进行简单描述统计如下:


      很明显,每列都随机产生了一定数量的缺失值,接下来我们来对这份数据进行清洗。


  1. 了解缺失值的分布情况,这里我们通过VIM包中的aggr()函数对缺失值分布进行可视化:


> library(colorspace)
> library(grid)
> library(data.table)
> library(VIM)
> aggr(df2,prop=FALSE,numbers=TRUE)

      图中显示:Tel变量有21个缺失,Sex变量有28个缺失,Age变量有6个缺失,Freq变量有20个缺失,Amount变量有13个缺失,ATV有12个缺失。

      2.针对不同的变量及其具体内容,我们对Tel变量缺失的观测进行剔除、对Sex变量的缺失值用众数替换、对Age变量用平均值替换、对(Freq变量、Amount变量和ATV变量)用多重插补法填充:

> #剔除Tel变量的缺失观测
> df3 <- df2[is.na(df2$Tel)==FALSE,]
> #分别用众数和均值替换性别和年龄
> #性别的众数
> Sex_mode <- names(which.max(table(df3$Sex)))#此语句等同于Sex_mode <- df3$Sex[which.max(table(df3$Sex))]
> #年龄的均值
> Age_mean <- mean(df3$Age, na.rm = TRUE)
> library(tidyr)
> df3 <- replace_na(df3,replace = list(Sex = Sex_mode, Age = Age_mean))

      再次通过summary()函数对df3进行简单描述统计如下:


     由上图可知Tel变量、Sex变量和Age变量已经不存在缺失值,接下来通过mice包对Freq变量、Amount变量和ATV变量进行多重插补。该包可以对数值型数据和因子型数据进行插补。对于数值型数据,默认使用随机回归添补法(pmm);对二元因子数据,默认使用Logistic回归添补法(logreg);对多元因子数据,默认使用分类回归添补法(polyreg)。其他插补法,可通过?mice查看相关文档。

> library(lattice)
> library(mice)
> imp <- mice(data = df3, m = 5)
> Freq_imp <- apply(imp$imp$Freq,1,mean)
> Amount_imp <- apply(imp$imp$Amount,1,mean)
> ATV_imp <- apply(imp$imp$ATV,1,mean)
> df3$Freq[is.na(df3$Freq)] <- Freq_imp
> df3$Amount[is.na(df3$Amount)] <- Amount_imp
> df3$ATV[is.na(df3$ATV)] <- ATV_imp

      以上就是重复值清洗的全部过程。

二、异常值

1.识别异常值

       一般我们通过四分位距来识别异常值,我们把上四分位数和下四分位数之差定义为四分卫距,把超过上四分位数1.5倍四分位距和低于下四分位数1.5倍四分位距的数据认定为异常值,举例:

> set.seed(1234)
> value <- c(rnorm(100, mean = 10, sd = 3), runif(20, min = 0.01, max = 30), rf(30, df1 = 5, df2 = 20))
> #绘制箱线图,并用红色的方块标注出异常值
> library(ggplot2)
> ggplot(data = NULL, mapping = aes(x = '', y = value)) + geom_boxplot(outlier.colour = 'red', outlier.shape = 15, width = 1.2)


      由箱线图可知,有一部分数据落在上四分位数的1.5倍四分位距之上,即异常值,接下来我们将其找出:

> #计算下四分位数、上四分位数和四分位距
> QL <- quantile(value, probs = 0.25)
> QU <- quantile(value, probs = 0.75)
> QU_QL <- QU-QL
> which(value > QU + 1.5*QU_QL)
[1] 104 106 110 114 116 118 120
> value[which(value > QU + 1.5*QU_QL)]
[1] 23.03799 21.97173 29.56914 22.74426 27.96589 21.02544 25.51085

      由结果可知异常值分别为第104、106、110、114、116、118、120这7个点,处理异常值一般有两种方法,即剔除和替补,剔除很简单,重点讲讲替补:

> #用离异常点最近的点替换
> test01 <- value
> out_imp01 <- max(test01[which(test01 <= QU + 1.5*QU_QL)])
> test01[which(test01 > QU + 1.5*QU_QL)] <- out_imp01
> #用上四分位数的1.5倍四分位距或下四分位数的1.5倍四分位距替换
> test02 <- value
> out_imp02 <- QU + 1.5*QU_QL
> test02[which(test02 > QU + 1.5*QU_QL)] <- out_imp02

      以上就是异常值清理的过程。

      原文出处


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP