首页 > > > 【R语言】tidyverse之二:数据重塑
将新导入的数据变成整洁数据。
采用 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)
参考文献:
______________________
转载请注明,禁止用于出版。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3166475/ ,如需转载,请注明出处,否则将追究法律责任。