前言
本文为了迭代一个探索性数据分析的通用模式,首先使用银行信贷数据进行探索性数据分析,希望能够得到一个通用的强大探索性解决方案。
导入数据
数据是来自klaR的GermanCredit数据.
library(pacman)
p_load(tidyverse,klaR)
data(GermanCredit)
GermanCredit %>% as_tibble -> df
把表格数据已经导入到df中了。
整体把握
为了最快速地知道:-表格有多少行、多少列-表格的变量都是什么数据类型的-表格是否存在缺失值,如果存在,是如何缺失的-数据大体的分布
我们决定使用最便捷的函数。首先,DataExplorer包提供了一个快速仪表盘的生成,简单粗暴直接出报告,如果是Rstudio的用户能够马上得到一个report.html,在工作目录中生成。
p_load(DataExplorer)
create_report(df)
先用dlookr对表格进行审视:
p_load(dlookr)
diagnose(df) %>%
arrange(types) %>%
print(n = Inf)
## # A tibble: 21x 6
## variables types missing_countmissing_percent unique_count unique_rate
## <chr> <chr> <int> <dbl> <int> <dbl>
## 1status fact~ 0 0 4 0.004
## 2 credit_hi~fact~ 0 0 5 0.005
## 3purpose fact~ 0 0 10 0.01
## 4savings fact~ 0 0 5 0.005
## 5 personal_~fact~ 0 0 4 0.004
## 6 other_deb~fact~ 0 0 3 0.003
## 7property fact~ 0 0 4 0.004
## 8 other_ins~fact~ 0 0 3 0.003
## 9housing fact~ 0 0 3 0.003
## 10 job fact~ 0 0 4 0.004
## 11 telephone fact~ 0 0 2 0.002
## 12 foreign_w~ fact~ 0 0 2 0.002
## 13 credit_ri~ fact~ 0 0 2 0.002
## 14 duration nume~ 0 0 33 0.033
## 15 amount nume~ 0 0 921 0.921
## 16 installme~ nume~ 0 0 4 0.004
## 17 present_r~ nume~ 0 0 4 0.004
## 18 age nume~ 0 0 53 0.053
## 19 number_cr~ nume~ 0 0 4 0.004
## 20 people_li~ nume~ 0 0 2 0.002
## 21 employmen~ orde~ 0 0 5 0.005
上面的结果首先显示出来的,是数据名称及其类型,其次发现基本没有缺失,最后是看数据中有多少独特的取值。此外,我们还可以用skimr包。与上面的方法相比,这个方法会自动对数据类型进行分类,而且还会给出每一个独特的值的数量,对数值型变量会给出直方图分布示意图。
p_load(skimr)
skim(df)
## Skim summarystatistics
## n obs: 1000
## n variables:21
##
## -- Variable type:factor--------------------------------------------------------------------------------------------------
## variable missing complete nn_unique
## credit_history 0 1000 1000 5
## credit_risk 0 1000 1000 2
## employment_duration 0 1000 1000 5
## foreign_worker 0 1000 1000 2
## housing 0 1000 1000 3
## job 0 1000 1000 4
## other_debtors 0 1000 1000 3
## other_installment_plans 0 1000 1000 3
## personal_status_sex 0 1000 1000 4
## property 0 1000 1000 4
## purpose 0 1000 1000 10
## savings 0 1000 1000 5
## status 0 1000 1000 4
## telephone 0 1000 1000 2
## top_countsordered
## exi: 530,cri: 293, del: 88, all: 49 FALSE
## goo: 700, bad: 300, NA: 0 FALSE
## 1 <: 339, TRUE
## yes: 963, no: 37, NA: 0 FALSE
## own: 713,ren: 179, for: 108, NA: 0 FALSE
## ski: 630,uns: 200, man: 148, une: 22 FALSE
## non:907, gua: 52, co-: 41, NA: 0 FALSE
## non:814, ban: 139, sto: 47, NA: 0 FALSE
## mal: 548,fem: 310, mal: 92, mal: 50 FALSE
## car: 332,rea: 282, bui: 232, unk: 154 FALSE
## dom: 280,car: 234, rad: 181, car: 103 FALSE
## FALSE
## no : 394, FALSE
## no: 596, yes: 404, NA: 0 FALSE
##
## -- Variable type:numeric-------------------------------------------------------------------------------------------------
## variable missing complete n mean sd p0 p25 p50
## age 0 1000 1000 35.55 11.38 19 27 33
## amount 0 1000 1000 3271.26 2822.74 250 1365.52319.5
## duration 0 1000 1000 20.9 12.06 4 12 18
## installment_rate 0 1000 1000 2.97 1.12 1 2 3
## number_credits 0 1000 1000 1.41 0.58 1 1 1
## people_liable 0 1000 1000 1.16 0.36 1 1 1
## present_residence 0 1000 1000 2.85 1.1 1 2 3
## p75 p100 hist
## 42 75 ▇▇▆▃▂▁▁▁
## 3972.2518424 ▇▃▂▁▁▁▁▁
## 24 72 ▇▅▅▃▁▁▁▁
## 4 4 ▂▁▃▁▁▂▁▇
## 2 4 ▇▁▅▁▁▁▁▁
## 1 2 ▇▁▁▁▁▁▁▂
## 4 4 ▂▁▆▁▁▃▁▇
一个比较好的可视化方法,是visdat包。
p_load(visdat)
vis_dat(df)
如果数据中有缺失值,也能够很好地展现出来,但是目前这里没有缺失值。
单变量数据分布
如果大家没有选择DataExplorer包的定制化数据报告服务,那么可以利用函数直接来看。
p_load(DataExplorer)
#数值型变量的分布观察
plot_density(df)
#因子型变量的分布观察
plot_bar(df)
双变量数据分布
在这份数据中,响应变量是credit_risk,它代表着客户的守信水平,只有两个因子“Good”和“Bad”。我们想要看它和所有连续变量的关系。
#响应变量为因子变量,因子变量与数值变量的关系,用箱线图表示
plot_boxplot(df,by = "credit_risk")
如果想知道连续变量之间的关系,让我们做相关性矩阵图。
p_load(dlookr)
plot_correlate(df)
图中,越“椭圆”就越相关,蓝色是正相关,红色是负相关。如果连因子变量的相关性也想知道,那么就用DataExplorer包中的plot_correlation函数。
plot_correlation(df)
它会把所有因子变量都用one-hot编码转化为数值型变量,然后做一个大的相关分析矩阵。如果这不是你想要的,可以设置type参数,得到一个专门分析连续变量的图。
plot_correlation(df,type = "c")
不过,想要同时获得相关性的信息,首推PerformanceAnalytics这个包。
p_load(PerformanceAnalytics)
df %>%
select_if(is.numeric) %>% #这种图只能看数值型变量的相互关系
chart.Correlation()
对于数值型变量,这种能够同时观察分布、相关系数和显著性水平的图,非常地有效。
离群值处理
为什么要进行探索性数据分析?一方面是要对自己的数据表格有一个大致的认识,从而增进商务理解和数据理解,为后续的分析奠定基础。另一方面,就是看看数据有没有出问题,如果有缺失值,那么肯定需要插补或者删除;如果有离群值,那么也需要决定究竟是保留还是删掉。我们这份数据集是案例数据集,因此没有缺失值,不过离群点还是可以进行检测的。如果一个记录的某一数值远离其平均水平,那么认为这个记录是离群点。至于界定“远离平均水平”的标准,要视业务本身数据分布而定。经典的离群点检测法,是箱线图判断离群点的方法(统计学上称为Tukey’s fences),这是基于单变量的。这个方法大家可以在维基查询到,网址为
diagnose_outlier(df)
## # A tibble: 7 x 6
## variablesoutliers_cnt outliers_ratio outliers_mean with_mean
## <chr> <int> <dbl> <dbl> <dbl>
## 1 duration 70 7. 50.5 20.9
## 2 amount 72 7.2 10940. 3271.
## 3 installm~ 0 0 NaN 2.97
## 4 present_~ 0 0 NaN 2.84
## 5 age 23 2.3 68.5 35.5
## 6 number_c~ 6 0.6 4 1.41
## 7 people_l~ 155 15.5 2 1.16
## # ... with 1 more variable: without_mean<dbl>
6个列中,第一列为变量名称,第二列是离群值个数,后面分别是离群值比例、离群值均值、包含离群值的全体的均值、去除离群值的全体的均值。因为installment_rate和present_residence变量不存在利群值,因此无法计算离群值的均值。我们看到people_liable是担保人的数量,其实它应该被认定为一个分类变量,因为它的取值只有1和2,所以如果对这个离群值做处理显然是错误的。回归方法对离群值是敏感的,不过我们可以对变量先进行中心化、标准化,从而减少离群值的影响。如果想要得到整个数据质量报告,可以用dlookr的diagonse_report函数。
diagnose_report(df)
小结
探索性数据分析的下一步,应该是数据预处理(特征工程)。如果不了解业务和数据,那么预处理就无从谈起。因此我们做探索性数据分析的时候,需要尽可能地观察数据的特点,并思考其背后的原因。一般来说,探索性数据分析需要知道一下几点:
- 数据的行列数,即多少样本、多少特征
- 数据特征的属性,也就是说这些数据有多少分类变量、多少数值变量
- 数据特征的分布,数值变量要看密度分布,分类变量要看每个分类的占比
- 数据特征之间的相关性,是否存在共线性?解释变量与响应变量的关系是否明显?
- 数据是否存在缺失值?如果存在缺失值,是否能够解释缺失的原因?是随机缺失还是非随机缺失,或者是介于两者之间。是否能够根据其自身的特征和缺失的特点来进行插值,或者是应该剔除掉?(本案例没有出现这个情况,没有讨论,今后的案例会尝试讨论这个问题)
- 数据特征中是否存在离群值?离群值是什么原因导致的?是真实的还是因为错误的操作?为了进行建模,应该如何处理这些离群值?(z中心化?取对数?还是直接剔除掉)
总的来说,探索性数据分析就是对数据特征的挖掘过程,发现它们的特点,一方面加深我们对业务的认识,另一方面也防止明显的错误。以上均为个人对数据进行探索的一些方法,如果有更多探索性的方法,请各位大佬积极补充。希望能够最后迭代出一套较为通用的探索性数据分析方法,从而为广大的数据科学家带来便利。