本章展示如何使用可视化和转换来系统地浏览数据,这是统计学家称之为探索性数据分析(简称EDA)的任务。 EDA是一个迭代循环。
(1) 生成有关数据的问题。
(2) 通过可视化,转换和建模数据来搜索答案。
(3) 使用学到的知识来完善问题和/或产生新问题。
所需工具
library(tidyverse)
进行数据探索时,两种类型的问题总是有用的。大致表述为:
-
变量的变化趋势如何?
-
变量之间发生了什么类型的协变,相关性如何?
本节主要探索第一个问题,关注变量的分布。
变量:
(1)变量分布可视化
在R中,类别变量通常保存为因子或字符向量。 要检查分类变量的分布,使用条形图:
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut))
条形图的高度显示每个x值发生了多少观察。 可以使用
dplyr :: count()
手动计算这些值:
diamonds %>%
count(cut)
#> # A tibble: 5 x 2
#> cut n
#> <ord> <int>
#> 1 Fair 1610
#> 2 Good 4906
#> 3 Very Good 12082
#> 4 Premium 13791
#> 5 Ideal 21551
如果变量是连续的,要检查连续变量的分布,则使用直方图:
ggplot(data = diamonds) +
geom_histogram(mapping = aes(x = carat), binwidth = 0.5)
可以通过组合
dplyr :: count()
和
ggplot2 :: cut_width()
来手动计算:
diamonds %>%
count(cut_width(carat, 0.5))
#> # A tibble: 11 x 2
#> `cut_width(carat, 0.5)` n
#> <fct> <int>
#> 1 [-0.25,0.25] 785
#> 2 (0.25,0.75] 29498
#> 3 (0.75,1.25] 15977
#> 4 (1.25,1.75] 5313
#> 5 (1.75,2.25] 2002
#> 6 (2.25,2.75] 322
#> # … with 5 more rows
直方图将x轴划分为等距的条带,然后使用条形图的高度显示每个条带中的观测值数量。 可以使用binwidth参数设置直方图中间隔的宽度,该宽度以x变量为单位进行度量,不同的binwidth可以揭示不同的模式。
smaller <- diamonds %>%
filter(carat < 3)
ggplot(data = smaller, mapping = aes(x = carat)) +
geom_histogram(binwidth = 0.1)
如果希望在同一图中叠加多个直方图,建议使用
geom_freqpoly()
而不是
geom_histogram()
。
geom_freqpoly()
执行的计算与
geom_histogram()
相同,但是不是使用条形显示计数,而是使用线条。
ggplot(data = smaller, mapping = aes(x = carat, colour = cut)) +
geom_freqpoly(binwidth = 0.1)
(2)Typical values
在条形图和直方图中,高条形图显示变量的常用值,而短条形图显示较少见的值。 没有条形的地方会显示您的数据中未显示的值。
ggplot(data = smaller, mapping = aes(x = carat)) +
geom_histogram(binwidth = 0.01)
下面的直方图显示了黄石国家公园中272颗老忠实间歇泉的喷发时间(以分钟为单位)。 爆发时间似乎分为两类:短暂的爆发(大约2分钟)和长时间的爆发(4-5分钟),但两者之间几乎没有。
ggplot(data = faithful, mapping = aes(x = eruptions)) +
geom_histogram(binwidth = 0.25)
(3)离群值
离群值是不寻常的观察值; 似乎与模式不符的数据点。 有时离群值是数据输入错误; 其他时候,离群值表明重要的新科学。 当您拥有大量数据时,有时很难在直方图中看到离群值。 例如,从菱形数据集中获取y变量的分布。 离群值的唯一证据是x轴异常宽的限制。
ggplot(diamonds) +
geom_histogram(mapping = aes(x = y), binwidth = 0.5)
常见的观测值太多,以至于稀有值柱子太短,以至于看不到它们。 为了易于查看异常值,我们需要使用
coord_cartesian()
缩放到y轴的较小值:
ggplot(diamonds) +
geom_histogram(mapping = aes(x = y), binwidth = 0.5) +
coord_cartesian(ylim = c(0, 50))
(当需要放大x轴时,
coord_cartesian()
还具有
xlim()
参数。ggplot2还具有
xlim()
和
ylim()
函数,它们的工作原理略有不同:它们将数据丢弃在限制范围之外。)
这使我们看到存在三个异常值:0,〜30和〜60。 我们用
dplyr
将它们提出:
unusual <- diamonds %>%
filter(y < 3 | y > 20) %>%
select(price, x, y, z) %>%
arrange(y)
unusual
#> # A tibble: 9 x 4
#> price x y z
#> <int> <dbl> <dbl> <dbl>
#> 1 5139 0 0 0
#> 2 6381 0 0 0
#> 3 12800 0 0 0
#> 4 15686 0 0 0
#> 5 18034 0 0 0
#> 6 2130 0 0 0
#> 7 2130 0 0 0
#> 8 2075 5.15 31.8 5.12
#> 9 12210 8.09 58.9 8.06
(4)缺失值
如果在数据集中遇到了异常值,并且只想继续进行其余数据的分析,则有两个选择。
diamonds2 <- diamonds %>%
filter(between(y, 3, 20))
-
用缺失值替换异常值。
最简单的方法是使用
mutate()
将变量替换为修改后的副本。 可以使用
ifelse()
函数用NA替换不寻常的值:
diamonds2 <- diamonds %>%
mutate(y = ifelse(y < 3 | y > 20, NA, y))
除了ifelse之外,请使用
dplyr :: case_when()
。 当您想创建一个依赖于现有变量的复杂组合的新变量时,
case_when()
在
mutate
中特别有用。
ggplot2不会在图中绘制缺失值,会警告它们已被删除:
ggplot(data = diamonds2, mapping = aes(x = x, y = y)) +
geom_point()
#> Warning: Removed 9 rows containing missing values (geom_point).
要禁止显示该警告,请设置na.rm = TRUE:
ggplot(data = diamonds2, mapping = aes(x = x, y = y)) +
geom_point(na.rm = TRUE)
如果想了解是什么使缺失值的观测值与记录值的观测值不同。 例如,在
nycflights13 :: flights
中,dep_time变量中的缺失值表示航班已取消。 因此,您可能需要比较已取消和未取消时间的计划出发时间。 您可以通过使用
is.na()
创建一个新变量来提取包含缺失值的观测。
nycflights13::flights %>%
mutate(
cancelled = is.na(dep_time),
sched_hour = sched_dep_time %/% 100,
sched_min = sched_dep_time %% 100,
sched_dep_time = sched_hour + sched_min / 60
) %>%
ggplot(mapping = aes(sched_dep_time)) +
geom_freqpoly(mapping = aes(colour = cancelled), binwidth = 1/4)
参考:
https://r4ds.had.co.nz/exploratory-data-analysis.html