查看原文
其他

ggplot2读书笔记12:第九章 数据分析

2018-03-15 圈圈 生信小白学习记

本书的最后一个部分,Part III,Data Analysis。主要包括三个章节,今天先来看第九章:

Data Analysis

9.1 简介

在前面的学习中,我们使用的模拟数据集都是已经整理好的数据框,可以直接使用。但通常实际数据并不会这么理想,需要通过一定的整理好变换才能用于作图

所以这个部分的目标就是把ggplot2和其他工具结合起来,用于完整的数据分析。

  • 首先学习整理数据的原则,了解 dplyr以及 tidyr等可以用于整理凌乱数据集的R包

  • 大多数可视化需要进行数据转换,可能要在现有变量的基础上,创造新的变量;或者执行简单的聚合。这些在第十章中有详细说明。

  • 使用R建模的过程中,如何将模型转换成整洁的数据集,这些在第十一章中可以稍作了解。

在本章中,作者用了两个事例来介绍怎样整理数据。

9.2 整理数据(Tidy Data)

整理数据的原则很简单:用一致的方式存储数据。(storing your data in a consistent way)

所以整理数据的目的是为了创造一个数据框的统计学结构(变量和观测数据)和物理结构(列和行)之间的映射。

其中,

变量放在中(Variables go in columns)

观测数据放在中(Observations go in rows)

我们需要先安装几个R包, dplyrtidyrmagrittr

下面加载一个需要整理的关于经济学失业率 economics数据集的子集 ec2,作为例子:

  1. > ec2

  2. # A tibble: 12 x 11

  3.   month `2006` `2007` `2008` `2009` `2010` `2011` `2012` `2013` `2014` `2015`

  4.   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>

  5. 1  1.00   8.60   8.30   9.00   10.7   20.0   21.6   21.0   16.2   15.9   13.4

  6. 2  2.00   9.10   8.50   8.70   11.7   19.9   21.1   19.8   17.5   16.2   13.1

  7. 3  3.00   8.70   9.10   8.70   12.3   20.4   21.5   19.2   17.7   15.9   12.2

  8. 4  4.00   8.40   8.60   9.40   13.1   22.1   20.9   19.1   17.1   15.6   11.7

  9. 5  5.00   8.50   8.20   7.90   14.2   22.3   21.6   19.9   17.0   14.5   NA  

  10. 6  6.00   7.30   7.70   9.00   17.2   25.2   22.3   20.1   16.6   13.2   NA  

  11. 7  7.00   8.00   8.70   9.70   16.0   22.3   22.0   17.5   16.3   13.5   NA  

  12. 8  8.00   8.40   8.80   9.70   16.3   21.0   22.4   18.5   16.8   13.3   NA  

  13. 9  9.00   8.00   8.70  10.2    17.8   20.3   22.0   18.8   16.5   13.3   NA  

  14. 10 10.0    7.90   8.40  10.4    18.9   21.2   20.5   19.7   16.1   13.5   NA  

  15. 11 11.0    8.30   8.60   9.80   19.8   21.0   20.9   18.5   17.0   12.8   NA  

  16. 12 12.0    7.50   8.40  10.5    20.1   21.9   20.5   17.6   17.0   12.6   NA  

PS. 这个 ec2不是ggplot2中自带的数据集,无法直接加载出来,通过万能的Google找到了加载ec2的方法,在此之前我们需要再多安装一个用于时间数据处理的r包 lubridate

  1. library(lubridate)

  2. library(magrittr)

  3. library(dplyr)

  4. library(tidyr)

  5. ec2 <-

  6.  ggplot2::economics %>%

  7.  tbl_df() %>%

  8.  transmute(year = year(date), month = month(date), rate = uempmed) %>%

  9.  filter(year > 2005) %>%

  10.  spread(year, rate)

  11. ec2

这个数据集的混乱之处在于,变量 yearmonth分别是列名和行名,观测结果在每个小单元里。

然后我们需要用两对工具:

  • Spread & gather

  • Separate & unite

9.3 Spread and Gather

先看一下这俩表格有啥区别:

  1. > indexed <- data.frame(

  2. +   x = c("a", "b", "c", "d", "c"),

  3. +   y = c("A", "D", "A", "C", "B"),

  4. +   z = c(1, 5, 4, 9, 10)

  5. + ) %>% arrange(x, y)

  6. > matrix <- indexed %>% spread(y, z)

  7. >

  8. > knitr::kable(indexed)

  9. |x  |y  |  z|

  10. |:--|:--|--:|

  11. |a  |A  |  1|

  12. |b  |D  |  5|

  13. |c  |A  |  4|

  14. |c  |B  | 10|

  15. |d  |C  |  9|

  16. > knitr::kable(matrix)

  17. |x  |  A|  B|  C|  D|

  18. |:--|--:|--:|--:|--:|

  19. |a  |  1| NA| NA| NA|

  20. |b  | NA| NA| NA|  5|

  21. |c  |  4| 10| NA| NA|

  22. |d  | NA| NA|  9| NA|

(这里面用到了一个表格生成函数 knitr::kable())

这两种表格分别称为“索引数据”(通过变量值查找数据)和“笛卡尔数据”(通过查看行和列的交集来找到一个值)

tidyr包包含两个函数 gather()spread() 可以用来执行以下操作:

  • gathering:从笛卡尔数据翻译成索引数据


  • spreading:从索引数据翻译成笛卡尔数据


Gather

gather()函数包含以下四个参数:

  • data:需要转换的数据集

  • key:将从列名创建出的变量名称

  • value:将从每个单元创建出的变量名

  • ...:要收集哪些变量,可以一个一个列出来,也可以使用简写形式 ..:..

所以我们要整理上面的ec2数据集,就要把所有变量放在列中。其中只有 month在列中, yearrate还是“笛卡尔数据形式”,所以我们要把他们转换成“索引形式”,可生成以下数据集:

注意2006-2015不是R语言中标准的变量名称(不是以字母开头)所以我们需要用单括号括起来

  1. > gather(ec2, key = year, value = unemp, `2006`:`2015`)

  2. # A tibble: 120 x 3

  3.   month year  unemp

  4.   <dbl> <chr> <dbl>

  5. 1  1.00 2006   8.60

  6. 2  2.00 2006   9.10

  7. 3  3.00 2006   8.70

  8. 4  4.00 2006   8.40

  9. 5  5.00 2006   8.50

  10. 6  6.00 2006   7.30

  11. 7  7.00 2006   8.00

  12. 8  8.00 2006   8.40

  13. 9  9.00 2006   8.00

  14. 10 10.0  2006   7.90

  15. # ... with 110 more rows

另一种方法(gather除了month之外的数据):

  1. gather(ec2, key = year, value = unemp, -month)

增加两种参数,可以更加严谨:

  1. economics_2 <- gather(ec2, year, rate, `2006`:`2015`,

  2.                      convert = TRUE, na.rm = TRUE)

  3. economics_2

其中

convert=TRUE自动将年份从字符串转换为数字

na.rm=TRUE自动删除没有数据的月份

当数据处于这种形式时,比较容易可视化:

  1. library(ggplot2)

  2. ggplot(economics_2, aes(month, rate, group = year)) +

  3.  geom_line(aes(colour = year), size = 1)

  1. ggplot(economics_2, aes(year + (month - 1) / 12, rate)) +

  2.  geom_line()

Spread

spread()是与 gather()相对应的另一种函数。

如下例,创建weather数据集,包含三个变量,分别是 day, raintemp

  1. weather <- dplyr::data_frame(

  2.  day = rep(1:3, 2),

  3.  obs = rep(c("temp", "rain"), each = 3),

  4.  val = c(c(23, 22, 20), c(0, 0, 5))

  5. )

输出如下“索引模式”

  1. > weather

  2. # A tibble: 6 x 3

  3.    day obs     val

  4.  <int> <chr> <dbl>

  5. 1     1 temp  23.0

  6. 2     2 temp  22.0

  7. 3     3 temp  20.0

  8. 4     1 rain   0  

  9. 5     2 rain   0  

  10. 6     3 rain   5.00

通过 spread()可以将繁琐的索引数据转变成简洁的笛卡尔数据形式。

参数和 gather()类似,如下例:

  1. > spread(weather, key = obs, value = val)

  2. # A tibble: 3 x 3

  3.    day  rain  temp

  4.  <int> <dbl> <dbl>

  5. 1     1  0     23.0

  6. 2     2  0     22.0

  7. 3     3  5.00  20.0

9.4 Separate and Unite

当多个变量被放在了一列中,或者很多列中有一个变量时,我们使用 separate()unite()函数。

如下例:

  1. trt <- dplyr::data_frame(

  2.  var = paste0(rep(c("beg", "end"), each = 3), "_", rep(c("a", "b", "c"))),

  3.  val = c(1, 4, 2, 10, 5, 11)

  4. )

数据集中包含三个变量(time, treatment 和 value),但是time和treatment混在了同一列中:

  1. > trt

  2. # A tibble: 6 x 2

  3.  var     val

  4.  <chr> <dbl>

  5. 1 beg_a  1.00

  6. 2 beg_b  4.00

  7. 3 beg_c  2.00

  8. 4 end_a  10.0

  9. 5 end_b  5.00

  10. 6 end_c  11.0

separate()函数包括:

  • data:要修改的数据框

  • col:要分隔的列

  • into:给新变量命名的字符向量

  • sep:描述如何分开这些变量

在上面的例子中:

  1. > separate(trt, var, c("time", "treatment"), "_")

  2. # A tibble: 6 x 3

  3.  time  treatment   val

  4.  <chr> <chr>     <dbl>

  5. 1 beg   a          1.00

  6. 2 beg   b          4.00

  7. 3 beg   c          2.00

  8. 4 end   a          10.0

  9. 5 end   b          5.00

  10. 6 end   c          11.0

unite()separate()的反函数,但并不常用。


参考资料:

  1. Hadley Wickham(2016). ggplot2. Springer International Publishing. doi: 10.1007/978-3-319-24277-4

  2. 《R语言应用系列丛书·ggplot2:数据分析与图形艺术》

  3. https://github.com/hadley/ggplot2-book/blob/master/tidy-data.rmd

-------------------我是求关注的分界线--------------

欢迎大家跟我一起上车:


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存