[数据分析] 使用R做EDA分析的基础知识
序言
因为最近想要给公司做一些预测性模型来标注保单的取消风险而提取了一些相关的数据,在使用机器学习模型之前按照惯例需要对数据进行一些探索性分析(EDA, Exploratory Data Analysis)
,并可能以此结果来指导机器学习模型的建造。那么在这篇里就先介绍一些EDA分析的例行步骤,以及如何使用R
来实现这些步骤。
正文
我在查找资料的时候发现了一个针对EDA教学且解释非常细致的教学网站,是Data Carpentry为生态学家使用R分析数据做的基础指南,虽然在标题中表现出相当的特殊性,但实际内容却是针对EDA分析的一般性知识。我会根据他的内容和结构大致介绍如何使用R来进行EDA分析。
读取数据
使用R做数据分析必须要介绍的一个包就是Tidyverse,这是一个集合了数据收集,转换,清洗,可视化等一系列满足数据科学需求的包的集合。Tidyverse
中包括的reader
包就是用来读取数据的工具,通常我们会使用read_csv()
包来将csv文件
读取为R中的数据框对象。
关于read_csv()
的参数设置,如果直接以文件名读取文件而不设置任何参数的话,经常会导致如下图所示,第一列数据表头的读取错误,这时我们需要在函数中加入fileEncoding = "UTF-8-BOM"
,因为read_csv()
默认解码方式是使用无BOM的UTF-8
,这样读取一些带有BOM这种文件头的文件就会被错误解码。
另外两个我用得比较多的参数是stringsAsFactors
和na.strings
。stringsAsFactors
设置为TRUE
时R会将文件中读取的字段按因子(factor)
处理,这样当数据中需要作为训练使用的字符串格式字段较多时不需要将他们逐一转换为因子格式。na.strings
则被用于认定丢失值,也就是说数据中出现这个参数设置的值时这条数据会被认为NA
。read_csv()
的使用示例如下 :
1 | df.raw <- read.csv("data_clean.csv", fileEncoding = "UTF-8-BOM", stringsAsFactors = TRUE,na.strings = c(""," ")) |
数据检视
数据拿到手的第一件事是查看数据的大致情况,R有一些简单的公式可以让分析师对数据有一些快速简单的了解。
1 | class(df.raw) # 返回对象的类型,例如data.frame |
数据框数据
数据框格式(data frame)
数据是数据分析中最常见的数据格式之一,它的特点是将数据以表格的形式储存,每一列都是一个长度相等的向量(vector)
,而每一行则代表一条数据,由于列的本质是向量,因此每列中的数据类型都应该相同。数据框数据的引用方法:
1 | df.raw[2,6] #选出第2行第6列的数据,以数据框格式返回 |
因子
因子(factors)
是R中存储分类数据(categorical data)
时所用的一种特色的数据格式,这些数据的特点是它们会从有限数量的可能值中取值。一个因子类的变量一旦被创建,它就只能从预设集中取值,这些预设集被称为水平值(levels)
,而因子变量本身则被以与这些水平集中的标签(labels)
一一对应的整数
储存。因此虽然因子变量看起来像字符变量,但实际上在数据处理时他们是被当成整型向量
处理。
将其他类型变量转换为因子类型
虽然我们在读取数据时已经设置过了将字符串形式数据以因子形式储存,但即使不这样做我们也可以用factor()
方程来手动将需要转换的字符型列转换为因子型。
1 | df.raw$id <- factor(df.raw$id) |
将因子变量水平值排序
通常R会按字母顺序排列水平值并编号,但有些时候由于水平值本身有顺序含义(例如大中小),因此R也提供了手动将水平值排序的功能。
1 | df.raw$id <- factor(df.raw$id, levels = c("第一","第二", "第三")) |
因子型变量转换为其他类型
如果需要将因子类型转换为数字或字符类型需要注意一点,因为因子类型本身以数字形式储存,所以直接对因子类型数据使用as.numeric()
会导致变量被直接转换为因子储存的整数索引值,正确方法应该如下:
1 | as.character(sex) #因子型转换为字符型时可以直接使用as.character |
因子水平值重命名
在R中,如果一个因子变量中存在缺失值,这些缺失值会被默认忽视,他们不会有自己的水平值。但事实情况中存在一些留有信息的缺失值,比如因为特定情况导致特定记录的值无法采集,这种情况下如果忽略这些缺失值实际上是丢失了有效信息,因此不同情况下我们也需要把缺失值放入水平值集中并可能需要重命名。
1 | sex <- surveys$sex |
总结下来就是使用addNA()
可以将缺失值加入因子型变量中,然后使用levels(sex)[3] <- "undetermined"
则可以将undetermined
赋值给sex
的第3
个水平值。
数据清洗
在这一步中我们需要挑选,调整,创建一系列的变量,来达到获得理想的适合进行数据分析的数据集的结果。我们首先介绍一些tidyverse
中dplyr
包的功能,这个包中的函数可以实现上面提到的大部分数据操作。
挑选和筛选
要做数据清洗首先需要的第一个功能就是以特定需求挑选所需的数据,dplyr
包中的select()
和filter()
就是分别用来挑选数据列和行的。具体用法如下:
1 | select(df.raw, id, sex, age) # 第一个参数为数据框,其他为需要挑选的列 |
通常在我们处理数据集时要将数据集先后进行各种操作,如果将他们逐一赋值或嵌套会非常混乱且麻烦,因此dplyr
也提供了方便的pipe
功能,可以将前一步操作的结果直接输入下一步操作的第一个参数。例如我们想要从df.raw
中先筛选出性别为M
的记录,然后选出他们的age
与id
作为数据集:
1 | df.raw %>% #将df.raw输入到下一步 |
上方步骤中,%>%
这个符号是代表pipe
的操作符,在Rstudio
中可以使用Ctrl + Shift + M
来快速输入。
is.na()
is.na()
公式是在用来判断对象是否为缺失值的公式,可以配合filter()
公式使用来排除某列中为空的记录:
1 | df.raw %>% |
创建新列
通常如果我们需要在数据集中根据已有列创建新列,就需要使用mutate()
函数。他的使用方法非常简单:
1 | mutate(df.raw, salary_in_k = salary/1000) # 创建一个名叫salary_in_k的列,内容为salary/1000 |
而我们通常在创建新列的时候除了进行计算,也会做一些例如判断或将连续变量离散化分组的操作,下面介绍的两个函数就可以帮助完成这两个操作。
cut()
cut()
函数可以被用来对连续变量进行离散化分组,实际用法如下:
1 | df.raw %>% |
该函数中,breaks
参数既可以取不同取值点,也可以使用整数表示将区间平分为整数个。include.lowest
设定为TRUE
时分组区间的最左边区间会取双闭区间。其他参数或具体示例可以参考该网站。
ifelse()
ifelse()
函数可以用来做各种判断取值,实际用法如下:
1 | df.raw %>% |
数据分组计算
有些情况下我们需要对一些数据进行分组的计算和整理,比如统计某个特定分类的数量或者平均值,或者这个分类中各个更小的分类占这个分类数量的半分比等,就可以用group_by()
这个函数实现,以我给公司分析的数据中使用的代码举例:
1 | # check the percentage of renewal for each product at each renewal point --------------- |
需要注意的一点是在上面代码的第二部分,我们Total = sum(count)
的操作虽然是针对所有行,但sum
本身却由于前面的group_by(CNTTYPE)
只针对CNTTYPE
中的每一个factors
,以此算出了每个单独的CNTTYPE
的和。
arrange()
arrange()
函数可以用来将数据框以特定列的数值排列,用法如下:
1 | df.raw %>% |
count()
对数据框对象使用count()
函数并指定特定列名,效果等同于以该列分组后计数。实际使用如下:
1 | df.raw %>% |
数据可视化
探索性分析的最后一步就是将处理好的数据进行对比展示从而得出所需信息了,tidyverse
中使用ggplot2
来进行数据可视化。本节我会首先介绍下ggplot2
的函数使用的基本格式,然后介绍一些常见的函数和参数,这里最后附上一个ggplot2
的详细的文档网站。
函数格式
之所以专门要说一说函数的格式是因为ggplot
的函数使用格式与其他常见包有较大的区别,当需要在一张图上增加不同功能或元素时不同部分之间使用+
号连接。
ggplot(data = , mapping = aes(
)) + <GEOM_FUNCTION>()
ggplot()
ggplot()
是ggplot2
作图的最基础的模块,在这个函数内指定作图的数据源,同时在这个函数中我们也可以使用aes()
函数设置图片可视化的不同维度。使用方法如下:
1 | ggplot(data = df.raw, # data参数中指定使用的数据集 |
需要强调一下aes()
的使用方法,该函数本身用来指定需要制作的图的各个参数,可以在ggplot()
中设定,也可以在各层GEOM_FUNCTION
中单独设置。其中fill
这个参数如果使用特定颜色则表示使用改颜色填充图,若使用某个因子型变量则代表在图中使用不同颜色标明这个变量的不同值。
常用图类型及参数设置
geom_point():
根据数据绘制点图,size
,color
,shape
三个参数分别可以控制点的大小
,颜色
和形状
。可以增加geom_rug()
,geom_density_2d()
或stat_ellipse()
等功能增强显示,具体参见此页面。geom_smooth():
对点图绘制回归线,method
参数可以选择默认的loess
或lm
,后者可以通过formula = y ~ poly(x, 3)
参数指定回归的次数,se
参数设定为TRUE
时显示回归线的置信区间,fullrange
设定为TRUE
时回归线会跨过整个图,level
参数是置信水平,默认为0.95
。geom_line():
根据数据点绘制线图,可以使用linetype
调整线的形状,在group
参数中可以对不同的分组绘图。geom_abline():
在图中添加线,intercept
和slope
参数分别设定线的截距和斜率。除了abline()
以外还有vline()
,hline()
,geom_segment()
。具体使用参见此页面。geom_boxplot():
绘制箱型图,outlier.colour
,outlier.shape
,outlier.size
三个参数分别设置异常值的颜色,形状和大小。另外有一个notch
参数设置为TRUE
时将绘制展示中位数置信区间的箱型图,用以对比两组数据中位数的差异。可以配合geom_dotplot()
或geom_jitter()
在箱型图中绘制点分布,具体使用参见此页面。geom_bar():
柱状图,stat
参数若为identity
则y轴以y值计算,若为bin
则y轴以记录数计算,position
参数可以为dodge,stake
或fill
来对比,堆叠或百分比显示柱状图。另外可以使用coord_flip()
翻转坐标轴或使用coord_polar("y", start=0)
来制作饼图。其他更多设置参考此页面geom_histogram():
直方图,用于展示数据的分布情况。也可以像柱状图一样使用position
参数调整不同组数据的展示方式,alpha
参数用于调整图像透明度。更多使用方法参考此页面。geom_density():
概率分布图,与直方图效果类似,但是使用曲线围出的面积为1的概率分布图来描述不同值出现的概率,可以配合直方图展示。
其他常用函数
多面对比(Faceting)
facet_wrap(facets = vars(sex))
或facet_grid(rows = vars(sex), cols = vars(age))
可以分别以两种方式制作多图对比。效果如下:
要将多图对比时也可以使用图1 + 图2 + plot_layout()
的表达方式将多图展示,该用法需要先安装patchwork
的包,具体参数及用法参见该网站。
设置图标签
geom_text():
该函数可以在图中标出各点的文字信息,用法如geom_text(label=rownames(mtcars))
。
labs():
可以使用该函数修改图片的各个文字标签,主要参数有title
修改图标题,x
修改x轴标注,y
修改y轴标注,fill
修改legend标注等。
图片主题
theme_gray():
灰色背景与白色格线。
theme_bw():
白色背景与灰色格线。
theme_linedraw():
在theme_bw()的基础上图界有黑线包裹。
theme_light():
浅灰色线与轴,更凸显数据本身。
theme_minimal():
几乎没有背景标记。
theme_classic():
R的经典图片格式,有图片边框无格线。
theme_void():
无任何标记。
theme_dark():
暗灰色背景,适用于颜色丰富的图片。