有时候我们需要将数据展现的形式转换成另外一种样式的时候(比如将一列或多列数据纳入一列中),这个时候我们应该怎么做呢?倘若我们自己写代码完成的话,可能就会比较费时。这个时候我们可以使用 tidyverse 包中的提供的数据整理工具,这花费更少的时间将数据从一种表示转换为另一种表示,这样我们就会有更多的时间分析数据了。
1. 加载包
接下来我们将介绍tidyverse家族中的tidyr包,该包提供了一系列工具来整理凌乱的数据集。
library(tidyverse)
2. 整理数据
对同一数据集我们可以有不同的表示方式。下面的这个数据集(加载tidyverse后可直接查看)通过不同的方式显示了四个变量country、year、population和cases的值。
table1
#> # A tibble: 6 x 4
#> country year cases population
#> <chr> <int> <int> <int>
#> 1 Afghanistan 1999 745 19987071
#> 2 Afghanistan 2000 2666 20595360
#> 3 Brazil 1999 37737 172006362
#> 4 Brazil 2000 80488 174504898
#> 5 China 1999 212258 1272915272
#> 6 China 2000 213766 1280428583
table2
#> # A tibble: 12 x 4
#> country year type count
#> <chr> <int> <chr> <int>
#> 1 Afghanistan 1999 cases 745
#> 2 Afghanistan 1999 population 19987071
#> 3 Afghanistan 2000 cases 2666
#> 4 Afghanistan 2000 population 20595360
#> 5 Brazil 1999 cases 37737
#> 6 Brazil 1999 population 172006362
#> # … with 6 more rows
table3
#> # A tibble: 6 x 3
#> country year rate
#> * <chr> <int> <chr>
#> 1 Afghanistan 1999 745/19987071
#> 2 Afghanistan 2000 2666/20595360
#> 3 Brazil 1999 37737/172006362
#> 4 Brazil 2000 80488/174504898
#> 5 China 1999 212258/1272915272
#> 6 China 2000 213766/1280428583
# Spread across two tibbles
table4a # cases
#> # A tibble: 3 x 3
#> country `1999` `2000`
#> * <chr> <int> <int>
#> 1 Afghanistan 745 2666
#> 2 Brazil 37737 80488
#> 3 China 212258 213766
table4b # population
#> # A tibble: 3 x 3
#> country `1999` `2000`
#> * <chr> <int> <int>
#> 1 Afghanistan 19987071 20595360
#> 2 Brazil 172006362 174504898
#> 3 China 1272915272 1280428583
这些数据集虽然都来自同一数据,但它们的使用场合不一定相同。一个整理过的数据集,在 tidyverse 中使用起来会方便很多。
数据整理有三个相互关联的规则:
- 每个变量都必须有自己的列。
- 每个观察都必须有自己的行。
- 每个值都必须有自己的单元格。
下图显示了该规则。
数据集整理三个规则:变量在列中,观察值在行中,值在单元格中。为什么要进行数据整理呢?有两个主要优点:
dplyr、ggplot2 和 tidyverse 中的包都可以整理数据,下面就来说明一下如何使用table1
.
# Compute rate per 10,000
table1 %>%
mutate(rate = cases / population * 10000)
#> # A tibble: 6 x 5
#> country year cases population rate
#> <chr> <int> <int> <int> <dbl>
#> 1 Afghanistan 1999 745 19987071 0.373
#> 2 Afghanistan 2000 2666 20595360 1.29
#> 3 Brazil 1999 37737 172006362 2.19
#> 4 Brazil 2000 80488 174504898 4.61
#> 5 China 1999 212258 1272915272 1.67
#> 6 China 2000 213766 1280428583 1.67
# Compute cases per year
table1 %>%
count(year, wt = cases)
#> # A tibble: 2 x 2
#> year n
#> <int> <int>
#> 1 1999 250740
#> 2 2000 296920
# Visualise changes over time
library(ggplot2)
ggplot(table1, aes(year, cases)) +
geom_line(aes(group = country), colour = "grey50") +
geom_point(aes(colour = country))
image
3.数据转换
对于大多数实际的数据分析,需要进行进一步整理。首先要弄清楚变量和观察值是什么。接着你需要知道(1. 一个变量可能分布在多列中;2. 一项观察可能分散在多行中)
要解决这些问题,将需要用到 tidyr 中两个最重要的函数:pivot_longer()
和pivot_wider()
。
3.1 宽数据变长数据
有时候数据集的某些列名称不是变量名称,而是变量的值。如table4a
:列1999
和2000
代表year
变量的值,1999
和2000
列中的值代表cases
变量的值,每一行代表两个观察值,而不是一个。
table4a
#> # A tibble: 3 x 3
#> country `1999` `2000`
#> * <chr> <int> <int>
#> 1 Afghanistan 745 2666
#> 2 Brazil 37737 80488
#> 3 China 212258 213766
整理这样的数据集,我们需要转换列形成新的变量。为了描述该操作,我们需要三个参数:
-
名称为值而非变量的列集。在这个例子中,那些是列
1999
和2000
。 -
要将列名移动到的变量的名称。在这里
year
。 -
要将列值移动到的变量的名称。在这里
cases
。
通过调用pivot_longer()
来生成:
table4a %>%
pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "cases")
#> # A tibble: 6 x 3
#> country year cases
#> <chr> <chr> <int>
#> 1 Afghanistan 1999 745
#> 2 Afghanistan 2000 2666
#> 3 Brazil 1999 37737
#> 4 Brazil 2000 80488
#> 5 China 1999 212258
#> 6 China 2000 213766
由于year
和cases
开始不存在,table4a
所以我们将他们的名字放在引号中。
在最终结果中,要转换的列被删除,我们得到新的year
和cases
列。
pivot_longer()
通过增加行数和减少列数来使数据集更长。我认为将数据集描述为“长格式”是没有意义的。长度是一个相对术语,您只能说(例如)数据集 A 比数据集 B 长。
我们可以用类似的方式pivot_longer()
来整理table4b
。唯一的区别是存储在单元格值中的变量:
table4b %>%
pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "population")
#> # A tibble: 6 x 3
#> country year population
#> <chr> <chr> <int>
#> 1 Afghanistan 1999 19987071
#> 2 Afghanistan 2000 20595360
#> 3 Brazil 1999 172006362
#> 4 Brazil 2000 174504898
#> 5 China 1999 1272915272
#> 6 China 2000 1280428583
要将table4a
和table4b
的整理结果合并,我们需要使用dplyr::left_join()
。
tidy4a <- table4a %>%
pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "cases")
tidy4b <- table4b %>%
pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "population")
left_join(tidy4a, tidy4b)
#> Joining, by = c("country", "year")
#> # A tibble: 6 x 4
#> country year cases population
#> <chr> <chr> <int> <int>
#> 1 Afghanistan 1999 745 19987071
#> 2 Afghanistan 2000 2666 20595360
#> 3 Brazil 1999 37737 172006362
#> 4 Brazil 2000 80488 174504898
#> 5 China 1999 212258 1272915272
#> 6 China 2000 213766 1280428583
3.2 长数据变宽数据
pivot_wider()
是pivot_longer()
的反向操作。当观察值分散在多行中时,可以使用它。例如,假设table2
:一个观察是一年中的一个国家,但每个观察都分布在两行中。
table2
#> # A tibble: 12 x 4
#> country year type count
#> <chr> <int> <chr> <int>
#> 1 Afghanistan 1999 cases 745
#> 2 Afghanistan 1999 population 19987071
#> 3 Afghanistan 2000 cases 2666
#> 4 Afghanistan 2000 population 20595360
#> 5 Brazil 1999 cases 37737
#> 6 Brazil 1999 population 172006362
#> # … with 6 more rows
为了整理这些,我们首先以与pivot_longer()
类似的方式分析表示。然而,pivot_wider()
只需要两个参数:
-
从中获取变量名的列。在这里是
type
。 -
要从中获取值的列。在这里
count
。
table2 %>%
pivot_wider(names_from = type, values_from = count)
#> # A tibble: 6 x 4
#> country year cases population
#> <chr> <int> <int> <int>
#> 1 Afghanistan 1999 745 19987071
#> 2 Afghanistan 2000 2666 20595360
#> 3 Brazil 1999 37737 172006362
#> 4 Brazil 2000 80488 174504898
#> 5 China 1999 212258 1272915272
#> 6 China 2000 213766 1280428583
image.png
正如你可能已经从他们的名字猜到了,pivot_wider()
和pivot_longer()
是相互对立的。pivot_longer()
使宽数据变窄变长;pivot_wider()
使长数据变短变宽。
4. 拆分与合并
前面我们已经学会了如何整理table2
和table4
。对于table3
有一个不同的问题:我们有一列 ( rate
) 包含两个变量 (cases
和population
)。为了解决这个问题,我们需要这个separate()
函数。
4.1 separate()
separate()
是在出现分隔符的地方进行拆分,将一列拆分为多列。
table3
#> # A tibble: 6 x 3
#> country year rate
#> * <chr> <int> <chr>
#> 1 Afghanistan 1999 745/19987071
#> 2 Afghanistan 2000 2666/20595360
#> 3 Brazil 1999 37737/172006362
#> 4 Brazil 2000 80488/174504898
#> 5 China 1999 212258/1272915272
#> 6 China 2000 213766/1280428583
对于table3
:该rate
列同时包含cases
和population
变量,我们需要将其拆分为两个变量。separate()
获取要分隔的列的名称,以及要分隔后的列的名称,如图下面的代码所示。
table3 %>%
separate(rate, into = c("cases", "population"))
#> # A tibble: 6 x 4
#> country year cases population
#> <chr> <int> <chr> <chr>
#> 1 Afghanistan 1999 745 19987071
#> 2 Afghanistan 2000 2666 20595360
#> 3 Brazil 1999 37737 172006362
#> 4 Brazil 2000 80488 174504898
#> 5 China 1999 212258 1272915272
#> 6 China 2000 213766 1280428583
分隔`table3`
我们可以通过sep
参数来自定义设置要拆分的分隔符。
table3 %>%
separate(rate, into = c("cases", "population"), sep = "/")
仔细查看列类型:您会注意到cases
和population
列是字符串。这是separate()
中的默认方式:它保持列的类型不变。如果我们想转换类型,在separate()
使用convert = TRUE
转换为更好的类型:
table3 %>%
separate(rate, into = c("cases", "population"), convert = TRUE)
#> # A tibble: 6 x 4
#> country year cases population
#> <chr> <int> <int> <int>
#> 1 Afghanistan 1999 745 19987071
#> 2 Afghanistan 2000 2666 20595360
#> 3 Brazil 1999 37737 172006362
#> 4 Brazil 2000 80488 174504898
#> 5 China 1999 212258 1272915272
#> 6 China 2000 213766 1280428583
您还可以对sep
传递整数向量。separate()
将整数解释为要拆分的位置。正值从字符串最左侧的 1 开始;负值从字符串最右侧的 -1 开始。
table3 %>%
separate(year, into = c("century", "year"), sep = 2)
#> # A tibble: 6 x 4
#> country century year rate
#> <chr> <chr> <chr> <chr>
#> 1 Afghanistan 19 99 745/19987071
#> 2 Afghanistan 20 00 2666/20595360
#> 3 Brazil 19 99 37737/172006362
#> 4 Brazil 20 00 80488/174504898
#> 5 China 19 99 212258/1272915272
#> 6 China 20 00 213766/1280428583
4.2 unite()
unite()
是separate()
的倒数:它将多列合并为一列。与separate()
相比,使用它的频率要低得多,但是也是一个适用的工具。
我们可以使用unite()
来重新连接我们在上一个示例中创建的世纪和年份列。该数据保存为tidyr::table5。 unite()
需要一个数据框,要创建的新变量的名称,以及一组要组合的列。
table5 %>%
unite(new, century, year)
#> # A tibble: 6 x 3
#> country new rate
#> <chr> <chr> <chr>
#> 1 Afghanistan 19_99 745/19987071
#> 2 Afghanistan 20_00 2666/20595360
#> 3 Brazil 19_99 37737/172006362
#> 4 Brazil 20_00 80488/174504898
#> 5 China 19_99 212258/1272915272
#> 6 China 20_00 213766/1280428583
在这种情况下,我们还需要使用sep
参数。默认将在来自不同列的值之间放置一个下划线 ( _
)。这里我们不需要任何分隔符,所以我们使用""
:
table5 %>%
unite(new, century, year, sep = "")
#> # A tibble: 6 x 3
#> country new rate
#> <chr> <chr> <chr>
#> 1 Afghanistan 1999 745/19987071
#> 2 Afghanistan 2000 2666/20595360
#> 3 Brazil 1999 37737/172006362
#> 4 Brazil 2000 80488/174504898
#> 5 China 1999 212258/1272915272
#> 6 China 2000 213766/1280428583
5. 缺失值
更改数据集的时候我们可能会遇到缺失值,缺失值一般以两种方式存在:
-
明确地,即标记为
NA
。 - 隐含地,即根本不存在于数据中。
让我们通过一个非常简单的数据集来说明:
stocks <- tibble(
year = c(2015, 2015, 2015, 2015, 2016, 2016, 2016),
qtr = c( 1, 2, 3, 4, 2, 3, 4),
return = c(1.88, 0.59, 0.35, NA, 0.92, 0.17, 2.66)
)
此数据集中有两个缺失值:
- 2015 年第四季度的回报明显缺失,因为其值所在的单元格为
NA
. - 2016 年第一季度的回报隐含缺失,因为它根本没有出现在数据集中。
这两种缺失值的差异:显式缺失值是存在缺失值;隐式缺失值是不存在。
改变数据集的表示方式可以使隐式值显式。例如,我们可以通过在列中放置年份来明确隐式缺失值:
stocks %>%
pivot_wider(names_from = year, values_from = return)
#> # A tibble: 4 x 3
#> qtr `2015` `2016`
#> <dbl> <dbl> <dbl>
#> 1 1 1.88 NA
#> 2 2 0.59 0.92
#> 3 3 0.35 0.17
#> 4 4 NA 2.66
由于这些明确的缺失值可能不是在数据的其他表示中,你可以在pivot_longer()
设置values_drop_na = TRUE
转显性缺失值隐含的:
stocks %>%
pivot_wider(names_from = year, values_from = return) %>%
pivot_longer(
cols = c(`2015`, `2016`),
names_to = "year",
values_to = "return",
values_drop_na = TRUE
)
#> # A tibble: 6 x 3
#> qtr year return
#> <dbl> <chr> <dbl>
#> 1 1 2015 1.88
#> 2 2 2015 0.59
#> 3 2 2016 0.92
#> 4 3 2015 0.35
#> 5 3 2016 0.17
#> 6 4 2016 2.66
在整理的数据中明确缺失值的另一个重要工具是complete()
:
stocks %>%
complete(year, qtr)
#> # A tibble: 8 x 3
#> year qtr return
#> <dbl> <dbl> <dbl>
#> 1 2015 1 1.88
#> 2 2015 2 0.59
#> 3 2015 3 0.35
#> 4 2015 4 NA
#> 5 2016 1 NA
#> 6 2016 2 0.92
#> # … with 2 more rows
complete()
接受一组列,并找到所有唯一的组合。然后确保原始数据集包含所有这些值,并在必要时填充显式NA
。
您应该了解另一个重要的工具来处理缺失值。有时,当数据源主要用于数据输入时,缺失值表示应结转先前的值:
treatment <- tribble(
~ person, ~ treatment, ~response,
"Derrick Whitmore", 1, 7,
NA, 2, 10,
NA, 3, 9,
"Katherine Burke", 1, 4
)
您可以使用fill()
填充这些缺失值。它需要一组列,您希望将缺失值替换为最近的非缺失值(有时称为结转上次观察)。
treatment %>%
fill(person)
#> # A tibble: 4 x 3
#> person treatment response
#> <chr> <dbl> <dbl>
#> 1 Derrick Whitmore 1 7
#> 2 Derrick Whitmore 2 10
#> 3 Derrick Whitmore 3 9
#> 4 Katherine Burke 1 4
6. 相关案例
接下来,我们将通过实际案例来解决数据整理的问题。tidyr::who
数据集包含按年份、国家、年龄、性别和诊断方法细分的结核病 (TB) 病例。数据来自2014 年世界卫生组织全球结核病报告,可在此处下载。
该数据集中有大量流行病学信息,对于数据整理的需要有相当的挑战性:
who
#> # A tibble: 7,240 x 60
#> country iso2 iso3 year new_sp_m014 new_sp_m1524 new_sp_m2534 new_sp_m3544
#> <chr> <chr> <chr> <int> <int> <int> <int> <int>
#> 1 Afghan… AF AFG 1980 NA NA NA NA
#> 2 Afghan… AF AFG 1981 NA NA NA NA
#> 3 Afghan… AF AFG 1982 NA NA NA NA
#> 4 Afghan… AF AFG 1983 NA NA NA NA
#> 5 Afghan… AF AFG 1984 NA NA NA NA
#> 6 Afghan… AF AFG 1985 NA NA NA NA
#> # … with 7,234 more rows, and 52 more variables: new_sp_m4554 <int>,
#> # new_sp_m5564 <int>, new_sp_m65 <int>, new_sp_f014 <int>,
#> # new_sp_f1524 <int>, new_sp_f2534 <int>, new_sp_f3544 <int>,
#> # new_sp_f4554 <int>, new_sp_f5564 <int>, new_sp_f65 <int>,
#> # new_sn_m014 <int>, new_sn_m1524 <int>, new_sn_m2534 <int>,
#> # new_sn_m3544 <int>, new_sn_m4554 <int>, new_sn_m5564 <int>,
#> # new_sn_m65 <int>, new_sn_f014 <int>, new_sn_f1524 <int>,
#> # new_sn_f2534 <int>, new_sn_f3544 <int>, new_sn_f4554 <int>,
#> # new_sn_f5564 <int>, new_sn_f65 <int>, new_ep_m014 <int>,
#> # new_ep_m1524 <int>, new_ep_m2534 <int>, new_ep_m3544 <int>,
#> # new_ep_m4554 <int>, new_ep_m5564 <int>, new_ep_m65 <int>,
#> # new_ep_f014 <int>, new_ep_f1524 <int>, new_ep_f2534 <int>,
#> # new_ep_f3544 <int>, new_ep_f4554 <int>, new_ep_f5564 <int>,
#> # new_ep_f65 <int>, newrel_m014 <int>, newrel_m1524 <int>,
#> # newrel_m2534 <int>, newrel_m3544 <int>, newrel_m4554 <int>,
#> # newrel_m5564 <int>, newrel_m65 <int>, newrel_f014 <int>,
#> # newrel_f1524 <int>, newrel_f2534 <int>, newrel_f3544 <int>,
#> # newrel_f4554 <int>, newrel_f5564 <int>, newrel_f65 <int>
这是一个非常典型的数据集。它包含冗余列、奇数变量和许多缺失值。简而言之,who
它很乱,我们需要多个步骤来整理它。与 dplyr 一样,tidyr 可以将多个函数串联到一个管道中。
开始我们可以将不是变量的列聚集在一起。让我们来看看我们有什么:
-
country
、iso2
和iso3
看起来像是三个冗余的变量(指定国家/地区)。 -
year
显然也是一个变量。 -
我们还不知道所有其他列是什么,但鉴于变量名称中的结构(例如
new_sp_m014
,new_ep_m014
,new_ep_f014
),这些很可能是值,而不是变量。
所以我们需要把从new_sp_m014
到newrel_f65
的所有列聚集在一起。我们还不知道这些值代表什么,所以我们将给它们命名为"key"
。我们知道单元格代表病例数,因此我们使用变量cases
。当前表示中有很多缺失值,因此现在我们将使用values_drop_na
去掉缺失值,我们可以直接研究存在的值。
who1 <- who %>%
pivot_longer(
cols = new_sp_m014:newrel_f65,
names_to = "key",
values_to = "cases",
values_drop_na = TRUE
)
who1
#> # A tibble: 76,046 x 6
#> country iso2 iso3 year key cases
#> <chr> <chr> <chr> <int> <chr> <int>
#> 1 Afghanistan AF AFG 1997 new_sp_m014 0
#> 2 Afghanistan AF AFG 1997 new_sp_m1524 10
#> 3 Afghanistan AF AFG 1997 new_sp_m2534 6
#> 4 Afghanistan AF AFG 1997 new_sp_m3544 3
#> 5 Afghanistan AF AFG 1997 new_sp_m4554 5
#> 6 Afghanistan AF AFG 1997 new_sp_m5564 2
#> # … with 76,040 more rows
我们可以通过计算新列中的key
值的结构得到一些提示:
who1 %>%
count(key)
#> # A tibble: 56 x 2
#> key n
#> <chr> <int>
#> 1 new_ep_f014 1032
#> 2 new_ep_f1524 1021
#> 3 new_ep_f2534 1021
#> 4 new_ep_f3544 1021
#> 5 new_ep_f4554 1017
#> 6 new_ep_f5564 1017
#> # … with 50 more rows
您也许可以通过一些思考和一些实验自己解析出来:
- 每列的前三个字母表示该列是否包含新的或旧的结核病病例。在此数据集中,每一列都包含新案例。
- 接下来的两个字母描述了结核病的类型:
rel
代表复发病例ep
代表肺外结核病例sn
代表不能通过肺涂片(涂片阴性)诊断的肺结核病例sp
代表可以通过肺涂片(涂片阳性)诊断的肺结核病例
- 第六个字母给出了结核病患者的性别。该数据集按男性 (
m
) 和女性 (f
) 对案例进行分组。- 剩下的数字给出了年龄组。该数据集将案例分为七个年龄组:
014
= 0 – 14 岁1524
= 15 – 24 岁2534
= 25 – 34 岁3544
= 35 – 44 岁4554
= 45 – 54 岁5564
= 55 – 64 岁65
= 65 岁或以上
由于名称有点不一致,我们需要对列名的格式做一个小修正:将newrel
改成new_rel
(在这里很难发现这一点,但如果你不修复它,我们将在后续步骤中得到错误)。通过使用str_replace()
在字符“newrel”替换为“new_rel”。这使所有变量名称保持一致。
who2 <- who1 %>%
mutate(key = stringr::str_replace(key, "newrel", "new_rel"))
who2
#> # A tibble: 76,046 x 6
#> country iso2 iso3 year key cases
#> <chr> <chr> <chr> <int> <chr> <int>
#> 1 Afghanistan AF AFG 1997 new_sp_m014 0
#> 2 Afghanistan AF AFG 1997 new_sp_m1524 10
#> 3 Afghanistan AF AFG 1997 new_sp_m2534 6
#> 4 Afghanistan AF AFG 1997 new_sp_m3544 3
#> 5 Afghanistan AF AFG 1997 new_sp_m4554 5
#> 6 Afghanistan AF AFG 1997 new_sp_m5564 2
#> # … with 76,040 more rows
我们可以通过separate()
分割两次, 首先将在每个下划线处拆分代码。
who3 <- who2 %>%
separate(key, c("new", "type", "sexage"), sep = "_")
who3
#> # A tibble: 76,046 x 8
#> country iso2 iso3 year new type sexage cases
#> <chr> <chr> <chr> <int> <chr> <chr> <chr> <int>
#> 1 Afghanistan AF AFG 1997 new sp m014 0
#> 2 Afghanistan AF AFG 1997 new sp m1524 10
#> 3 Afghanistan AF AFG 1997 new sp m2534 6
#> 4 Afghanistan AF AFG 1997 new sp m3544 3
#> 5 Afghanistan AF AFG 1997 new sp m4554 5
#> 6 Afghanistan AF AFG 1997 new sp m5564 2
#> # … with 76,040 more rows
由于new
列在数据集中不变,我们将其删除,同时也删除掉多余的iso2
,iso3
列。
who3 %>%
count(new)
#> # A tibble: 1 x 2
#> new n
#> <chr> <int>
#> 1 new 76046
who4 <- who3 %>%
select(-new, -iso2, -iso3)
接着我们进行第二次拆分,将sexage
分为sex
和age
:
who5 <- who4 %>%
separate(sexage, c("sex", "age"), sep = 1)
who5
#> # A tibble: 76,046 x 6
#> country year type sex age cases
#> <chr> <int> <chr> <chr> <chr> <int>
#> 1 Afghanistan 1997 sp m 014 0
#> 2 Afghanistan 1997 sp m 1524 10
#> 3 Afghanistan 1997 sp m 2534 6
#> 4 Afghanistan 1997 sp m 3544 3
#> 5 Afghanistan 1997 sp m 4554 5
#> 6 Afghanistan 1997 sp m 5564 2
#> # … with 76,040 more rows
此时的who
数据集我们处理后得到的最终数据样式。
上面的每步操作,我们可以通过管道连接符,建立一个复杂的管道:
who %>%
pivot_longer(
cols = new_sp_m014:newrel_f65,
names_to = "key",
values_to = "cases",
values_drop_na = TRUE
) %>%
mutate(
key = stringr::str_replace(key, "newrel", "new_rel")
) %>%
separate(key, c("new", "var", "sexage")) %>%
select(-new, -iso2, -iso3) %>%
separate(sexage, c("sex", "age"), sep = 1)
网友评论