今天看啥  ›  专栏  ›  DumplingLucky

学习tidyverse - Tidy data

DumplingLucky  · 简书  ·  · 2021-05-16 09:39

“Tidy datasets are all alike, but every messy dataset is messy in its own way.” –– Hadley Wickham

本节中,我们将学习整理组织数据使其成为R可处理的整洁数据。

library(tidyverse)

1. Tidy data

可以通过多种方式表示相同的基础数据。 下面的示例显示了以四种不同方式组织的相同数据。

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内部更容易使用。

以下规则使数据集更整洁:



所以上面的三个数据集中只有table1是整洁的,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))

2. Pivoting(旋转)

大部分原始数据集需要进行一些整理。第一步要弄清楚什么是变量和观测值。。第二步是解决两个常见问题之一:

  • 一个变量可能分布在多列中。
  • 一种观察可能分散在多行中。
    要解决这些问题,需要在tidyr中使用两个最重要的功能: pivot_longer() pivot_wider()
(1) Longer

一个常见的问题是数据集中某些列名不是变量名,而是变量值。 以表4a为例:列名1999和2000代表year变量的值,1999和2000列中的值代表case变量的值,并且每一行代表两个观察值,而不是一个观察值。

table4a
#> # A tibble: 3 x 3
#>   country     `1999` `2000`
#> * <chr>        <int>  <int>
#> 1 Afghanistan    745   2666
#> 2 Brazil       37737  80488
#> 3 China       212258 213766

为了整理这样的数据集,我们需要将有问题的列旋转到一对新的变量中。

  • 名称为值而不是变量的列的集合。
  • 要将列名称移至的变量的名称。
  • 要将列值移动到的变量的名称。
    调用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

表4a中不存在年份和大小写,因此我们将其名称用引号引起来。


在最终结果中,删除了枢轴显示的列,我们得到了“新年”和“案例”列。
ivot_longer() 通过增加行数和减少列数来使数据集更长。
我们可以使用 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
(2) Wider

ivot_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() ,如下面以编程方式显示:
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

3. Separating and uniting

到目前为止,已经学习了如何整理table2和table4。 table3有一个不同的问题:我们有一个包含两个变量(个案和总体)的列(比率)。 要解决此问题,我们需要 eparate() 函数。 还将了解 eparate():unite() ,如果单个变量分布在多列中,则可以使用它们。

(1) Separate

通过在出现分隔符的位置进行拆分, split() 将一列拆分为多列。

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

费率列包含案例和总体变量,我们需要将其分为两个变量。 split() 将要分离的列的名称和要分离成的列的名称.

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


默认情况下, split() 会在看到非字母数字字符(即不是数字或字母的字符)的任何地方拆分值。 例如,在上面的代码中, split() 在正斜杠字符处分割rate的值。 如果希望使用特定字符分隔一列,则可以将该字符传递给 sepak() sep 参数。 例如,我们可以将上面的代码重写为:

table3 %>% 
  separate(rate, into = c("cases", "population"), sep = "/")

仔细查看列类型:您会注意到案例和填充是字符列。 这是 sepeparate() 中的默认行为:保留列的类型不变。我们可以要求 split() 尝试使用 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 split() 会将整数解释为要拆分的位置。 正值从字符串最左侧的1开始;否则为0。 负值从字符串最右边的-1开始。 使用整数分隔字符串时,sep的长度应比in中的名称数少一。

可以使用这种方式将每年的后两位数字分开。

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
(2) Unite

unite() split() 的反函数:它将多个列合并为一个列。


我们可以使用 unite() 重新加入在上一个示例中创建的 Century Year 列。 该数据另存为tidyr :: table5。 unite() 带有一个数据框,要创建的新变量的名称以及要组合的一组列,这些列再次以 dplyr :: select() 样式指定:

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

4. Missing values

更改数据集的表示形式会带来缺失值,可以通过以下两种可能的方式之一来处理缺失值:

  • 明确地,即标记为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

5. Case Study

tidyr :: who 数据集包含按年龄,国家,年龄,性别和诊断方法细分的结核病(TB)病例。 数据来自《 2014年世界卫生组织全球结核病报告》,网址为 http://www.who.int/tb/country/data/download/en/

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>

这是一个非常典型的现实示例数据集。它包含冗余列,奇数变量代码和许多缺失值。

  • 看起来country,iso2和iso3是三个冗余地指定国家/地区的变量。
  • 年份显然也是一个变量。
  • 鉴于变量名称中的结构(例如new_sp_m014,new_ep_m014,new_ep_f014),这些很可能是值,而不是变量。

因此,我们需要将从new_sp_m014到newrel_f65的所有列汇总在一起。我们尚不知道这些值代表什么,因此我们将其通用名称称为“键”。我们知道单元格代表案例数,因此我们将使用可变案例。当前表示形式中有很多缺失的值,所以现在我们将使用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

通过对它们进行计数,我们可以得到一些关于值结构的提示:

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

每列的前三个字母表示该列包含新的还是旧的TB病例。在此数据集中,每一列都包含新案例。
接下来的两个字母描述了结核的类型:

  • 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

然后,我们最好删除新列,因为它在此数据集中是恒定的。 在删除列时,我们还要删除iso2和iso3,因为它们是多余的。

who3 %>% 
  count(new)
#> # A tibble: 1 x 2
#>   new       n
#>   <chr> <int>
#> 1 new   76046
who4 <- who3 %>% 
  select(-new, -iso2, -iso3)

接下来,我们将第一个字符分开,将性别分为年龄和性别:

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)

参考: https://r4ds.had.co.nz/tidy-data.html




原文地址:访问原文地址
快照地址: 访问文章快照