数据清洗工作是数据分析必不可少,非常繁琐而又很重要的工作,在这里对初期数据清洗工作做个简单的总结。
我觉得非常好数据清洗训练是coursera上的课程,比如 Getting and Cleaning Data。
grep, grepl, sub, gsub
。数据清晰需要个标准,https://www.kaggle.com/c/house-prices-advanced-regression-techniques/data,我觉得数据如果能够清洗成这个样子会很不错,还要个data_discription文件。大致来说就是要:
需要特别注意是,因子变量一定不要和数值变量弄混了,否则会出现不必要的模型偏差。因此,我建议数据清洗时候避免把因子变量的层次设置成数字,建议设置成有实际意义的字符串。
为了得到标准的清洗数据,我们有写常见的任务,代码和函数如下:
dim(dat)
## 查看每个变量不同取值的个数
temp <- sapply(dat, function(x) length(unique(x))); str(temp)
## 查看变量不同取值较多的变量
temp[temp>100]
## 查看每个因子变量不同取值的个数
temp <- sapply(dat, function(x) ifelse(is.numeric(x), NA, length(unique(x)))) %>% na.omit
str(temp)
## 查看变量不同取值较多的因子变量
temp[temp>100]
replaceNA.by.mode <- function(x){
if (is.numeric(x))
x[which(is.na(x))] = median(na.omit(x))
else
x[which(is.na(x))] = as.factor(names(which(table(x) == max(table(x))))[[1]]) # 因子众数有多个,选取第一个
x
} # 用样本众数代替NA
temp <- sapply(dat, replaceNA.by.mode) %>% as.data.frame(); str(temp)
很多模型的效果好坏依赖于预测变量是否正态分布,所以有必要确定预测变量的正态性质。
################################################
## 查看数据是否正态分布有很多方法
#################################################
## 1. 图像法
temp <- dat$转让费 %>% (function(x) gsub("[^0-9]", "",x)) %>% as.numeric()
summary(temp)
hist(temp)
hist(log(temp +1))
qqnorm(temp %>% scale);abline(0,1, col = 2, pch =2, lwd = 4)
qqnorm(log(temp +1) %>% scale);abline(0,1, col = 2, pch =2, lwd = 4)
## 2. Kolmogorov-Smirnov正态性检验, 起修正检验Lilliefor检验也行
x <- log(temp +1) %>% scale
ks.test(temp, "pnorm")
ks.test(x, "pnorm")
ks.test(jitter(x), "pnorm")
nortest::lillie.test(temp)
nortest::lillie.test(x)
nortest::ad.test(x)
## 3. 小样本Shapiro-Wilk检验
shapiro.test(temp)
shapiro.test(x)
特征工程对于模型预测能力的提升非常,与数据清洗密切相关,有必要做一个简单的知识总结。
本章将会建立一些简单的函数,用于分析报告数据的清洗情况,以及特征工程的情况。使用本文件的方法如下:
knitr::knit("filepath")
dat <- read.csv("data.csv", header = T)
dim(dat) # 数据维度
## [1] 2271 86
##*************************************************************
## 查看每列缺失值的个数
temp <- sapply(dat, function(x) sum(is.na(x))); str(temp)
## Named int [1:86] 0 0 0 0 0 0 0 0 0 0 ...
## - attr(*, "names")= chr [1:86] "网址" "标题" "交易服务费" "转让费" ...
## 若某个特征缺失值太多,就可以去掉,对那种缺失值很少的变量可以采用样本众数替代。
##*************************************************************
## 查看每个变量不同取值的个数
temp <- sapply(dat, function(x) length(unique(x))); str(temp)
## Named int [1:86] 2271 2249 1 249 258 6 2 2 2 2 ...
## - attr(*, "names")= chr [1:86] "网址" "标题" "交易服务费" "转让费" ...
## 查看每个因子变量不同取值的个数
temp <- sapply(dat, function(x) ifelse(is.numeric(x), NA, length(unique(x)))) %>% na.omit
str(temp)
## atomic [1:6] 2271 2249 282 2271 28 2225
## - attr(*, "na.action")=Class 'omit' Named int [1:80] 3 4 5 6 7 8 9 10 11 12 ...
## .. ..- attr(*, "names")= chr [1:80] "交易服务费" "转让费" "租金" "流转方式" ...
## 查看变量不同取值较多的因子变量
temp[temp>100]
## 网址 标题 区域位置 地块编号 描述
## 2271 2249 282 2271 2225
## 如果特征的因子层次很多,通常这种变量需要进一步的处理。
##************************************************************
## 分析预测变量
## 考察预测变量的基本统计,如果预测变量是数值的,可以考察特征是否为或者可以化为正态分布
## 有多种方法可以使用,参考Ch1-2
# summary(data$预测变量)
##************************************************************
## 变化较少的变量
## 分析是否有常数变量
temp <- sapply(dat, function(x) length(unique(x)))
temp[temp ==1]
## 交易服务费
## 1
## 样本的经验分布
# ecdf(dat$转让费)
# unique(sort(dat$转让费)) %>% head
# sapply(unique(sort(dat$转让费)), ecdf(dat$转让费)) %>% (function(x) diff(c(0,x))) %>% head()
## 这是经验密度函数,由此就可以计算样本的gini系数, 如果某个特征过于接近于1,则需要处理
# (sapply(unique(sort(dat$转让费)), ecdf(dat$转让费)) %>% (function(x) diff(c(0,x))))^2 %>% sum
## 计算样本的gini系数
temp <- sapply(dat, function(x) (sapply(unique(sort(x)), ecdf(x)) %>% (function(x) diff(c(0,x))))^2 %>% sum)
temp[temp > 0.999]
## 交易服务费 厂地 果园地 菜地 养猪场 耕地
## 1.0000000 0.9991197 0.9991197 0.9991197 0.9991197 0.9991197
## 人工牧草地 X.火龙果. 山丘 客家文化屋 山边地 荒山岗地
## 0.9991197 0.9991197 0.9991197 0.9991197 0.9991197 0.9991197
## 山林地
## 0.9991197
## 这些变量变化太少,为了防止过拟合,他们是不会包含在模型中的。