美文网首页
7.数据整理

7.数据整理

作者: denghb001 | 来源:发表于2021-12-30 15:06 被阅读0次

    有时候我们需要将数据展现的形式转换成另外一种样式的时候(比如将一列或多列数据纳入一列中),这个时候我们应该怎么做呢?倘若我们自己写代码完成的话,可能就会比较费时。这个时候我们可以使用 tidyverse 包中的提供的数据整理工具,这花费更少的时间将数据从一种表示转换为另一种表示,这样我们就会有更多的时间分析数据了。

    1. 加载包

    接下来我们将介绍tidyverse家族中的tidyr包,该包提供了一系列工具来整理凌乱的数据集。

    library(tidyverse)
    

    2. 整理数据

    对同一数据集我们可以有不同的表示方式。下面的这个数据集(加载tidyverse后可直接查看)通过不同的方式显示了四个变量countryyearpopulationcases的值。

    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 中使用起来会方便很多。

    数据整理有三个相互关联的规则:

    1. 每个变量都必须有自己的列。
    2. 每个观察都必须有自己的行。
    3. 每个值都必须有自己的单元格。

    下图显示了该规则。

    数据集整理三个规则:变量在列中,观察值在行中,值在单元格中。

    为什么要进行数据整理呢?有两个主要优点:

    1. 选择一种相同的数据存储方式具有普遍优势。如果您拥有相同的数据结构,那么学习使用它的工具会更容易,因为它们具有潜在的一致性。
    2. 将变量放在列中有一个特定的优势,因为它可以让 R 的矢量化性质发挥作用。正如您在mutatesummary 函数中了解到的 ,大多数内置 R 函数都使用值向量。这使得转换整理过的数据就特别方便。

    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:列19992000代表year变量的值,19992000列中的值代表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
    

    整理这样的数据集,我们需要转换列形成新的变量。为了描述该操作,我们需要三个参数:

    • 名称为值而非变量的列集。在这个例子中,那些是列19992000

    • 要将列名移动到的变量的名称。在这里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
    

    由于yearcases开始不存在,table4a所以我们将他们的名字放在引号中。

    将“table4”转换成更长、更整洁的形式。

    在最终结果中,要转换的列被删除,我们得到新的yearcases列。

    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
    

    要将table4atable4b的整理结果合并,我们需要使用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. 拆分与合并

    前面我们已经学会了如何整理table2table4。对于table3有一个不同的问题:我们有一列 ( rate) 包含两个变量 (casespopulation)。为了解决这个问题,我们需要这个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列同时包含casespopulation变量,我们需要将其拆分为两个变量。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 = "/")
    

    仔细查看列类型:您会注意到casespopulation列是字符串。这是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() 相比,使用它的频率要低得多,但是也是一个适用的工具。

    合并`table5`

    我们可以使用unite()来重新连接我们在上一个示例中创建的世纪年份列。该数据保存为tidyr::table5unite()需要一个数据框,要创建的新变量的名称,以及一组要组合的列。

    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 可以将多个函数串联到一个管道中。

    开始我们可以将不是变量的列聚集在一起。让我们来看看我们有什么:

    • countryiso2iso3看起来像是三个冗余的变量(指定国家/地区)。

    • year 显然也是一个变量。

    • 我们还不知道所有其他列是什么,但鉴于变量名称中的结构(例如 new_sp_m014, new_ep_m014, new_ep_f014),这些很可能是值,而不是变量。

    所以我们需要把从new_sp_m014newrel_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
    

    您也许可以通过一些思考和一些实验自己解析出来:

    1. 每列的前三个字母表示该列是否包含新的或旧的结核病病例。在此数据集中,每一列都包含新案例。
    2. 接下来的两个字母描述了结核病的类型:
    • rel 代表复发病例
    • ep 代表肺外结核病例
    • sn 代表不能通过肺涂片(涂片阴性)诊断的肺结核病例
    • sp 代表可以通过肺涂片(涂片阳性)诊断的肺结核病例
    1. 第六个字母给出了结核病患者的性别。该数据集按男性 ( m) 和女性 ( f) 对案例进行分组。
    2. 剩下的数字给出了年龄组。该数据集将案例分为七个年龄组:
    • 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列在数据集中不变,我们将其删除,同时也删除掉多余的iso2iso3列。

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

    接着我们进行第二次拆分,将sexage分为sexage

    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)
    

    相关文章

      网友评论

          本文标题:7.数据整理

          本文链接:https://www.haomeiwen.com/subject/diriqrtx.html