ITPub博客

首页 > > > 【R语言】tidyverse之二:数据重塑

【R语言】tidyverse之二:数据重塑

作者:浪花小雨滴 时间:2020-06-17 10:48:05 0 删除 编辑

将新导入的数据变成整洁数据。

一. 什么是整洁数据?

采用 Hadley 的表述,脏的/不整洁的数据往往具有如下特点:

  • 首行(列名)是值,不是变量名;
  • 多个变量放在一列;
  • 变量既放在行也放在列;
  • 多种类型的观测单元在同一个单元格;
  • 一个观测单元放在多个表。

而整洁数据具有如下特点:

  • 每个变量构成一列;
  • 每个观测构成一行;
  • 观测单元的每个属性构成一个单元格。

Tidyverse 包和 R 函数操作的都是这种整洁数据:对变量重新编码、排序、计算,以及根据分析的需要变换出不同的数据子集。

而不整洁数据,首先需要变成整洁数据,这就是数据重塑。

下面看一个不整洁数据与整洁数据对比的例子:

observation 列有两个变量数据,列名中的 A/B 应是分类变量 species 的两个水平值,测量值列 count 和 dbh 应各占 1 列,而不是 2 列。

变成整洁表如下:

注:这里的关键是,要学会区分哪些是“变量”“观测”“值”。

二. 宽表变长表

宽表的特点是:表比较宽,本来该是”值“的,却出现在”变量“(名)中。

这就需要给它变到“值”中,新起个列名存为一列,这就是所谓的宽表变长表。

tidyr 包(1.0)提供了更先进的 pivot_longer() 函数来实现。

例 1 以 relig_income 数据集为例

relig_income

说明:religion 列不用动,变量(名)中的 `<$10k` 、`$10-20k` 等,是值,需要作为 1 列“值”来存放,新起一个列名 income;`<$10k` 、`$10-20k` 等列中的值,属于同一个变量,也需要指定一个列名 count:

relig_income %>% 
  pivot_longer(-religion, names_to = "income", values_to = "count")

例 2 多个值列的情形。先定义数据集:

family <- tribble(
  ~family,  ~dob_child1,  ~dob_child2, ~gender_child1, ~gender_child2,
  1L, "1998-11-26", "2000-01-29",      1L,        2L,
  2L, "1996-06-22",           NA,        2L,        NA,
  3L, "2002-07-11", "2004-04-05",      2L,        2L,
  4L, "2004-10-10", "2009-08-27",      1L,        1L,
  5L, "2000-12-05", "2005-02-28",      2L,        1L,
)
family <- family %>% mutate_at(vars(starts_with("dob")), parse_date)
family
family %>% pivot_longer(-family, 
                        names_to = c(".value", "child"), 
                        names_sep = "_", 
                        values_to = c("dob", "gender"),  # 该行可省略
                        values_drop_na = TRUE
                       ) 

说明:family 列不动,其余的列名以 "_" 分割,特殊参数 ".value" 指定部分列名("child1", "child2")变为变量 "child" 的“值”。

三. 长表变宽表

长表的特点是:表比较长。

有时候需要将分类变量的若干水平值,变成变量(列名)。这就是长表变宽表,它与宽表变长表正好相反(二者互逆)。

tidyr 包(1.0)提供了更先进的 pivot_wider() 函数来实现。

例 3 以 animals 数据集为例:

animals <- read_csv("data/mongolia_livestock/animal_numbers.csv", 
                    col_types = "cid") %>%
                    set_names("Type", "Year", "Heads")
animals %>%
  pivot_wider(names_from = Type, 
              values_from = Heads)

说明:names_form 指定列名来自哪个变量;values_from 指定"值"来自哪个变量。

四. 拆分列与合并列

拆分列与合并列也是正好相反(二者互逆)。

用 separate() 函数拆分列,基本语法为:

separate(data, col, into, sep, ...)

其中,col 为要拆分的列,into 为拆开的新列,按 sep 指定的分隔符拆分。

用 unite() 函数合并列,基本语法为:

unite(data, col, sep, ...)

其中,col 为要合并的列,sep 指定合并的分隔符。

最后,看一个综合的例子。

例 4 清洗世界银行的人口数据。

world_bank_pop

先从最显然的入手:年份跨过了多个列,应该宽表变长表:

pop2 <- world_bank_pop %>% 
  pivot_longer(`2000`:`2017`, names_to="year", values_to="value")
pop2

再来考虑 indicator 变量:

pop2 %>% count(indicator)

这里,SP.POP.GROW 为人口增长率,SP.POP.TOTAL 为总人口,SP.URB.* 也类似,只是城市的。将该列值拆分为两个变量:area(URB, POP)和 variable(GROW, TOTL):

pop3 <- pop2 %>% 
  separate(indicator, c(NA, "area", "variable"))
pop3

最后,再将分类变量 variable 的水平值变为列名(长表变宽表),就完成了清洗:

pop3 %>% 
  pivot_wider(names_from = variable, values_from = value)


参考文献:

  1. Desi Quintans, Jeff Powell. Working in the Tidyverse. hiercourse.com/
  2. tidy Vignettes: Pivoting, mirrors.tuna.tsinghua.edu.cn
  3. Garrett Grolemund, Hadley Wickham. R for Data Science. r4ds.had.co.nz/

______________________
转载请注明,禁止用于出版。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3166475/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: R语言-while语句
请登录后发表评论 登录
全部评论

注册时间:2018-05-16

  • 博文量
    4259
  • 访问量
    40389