【问题标题】:Simplifying gather() with pivot_longer() using multiple ID columns and value columns使用多个 ID 列和值列使用 pivot_longer() 简化gather()
【发布时间】:2021-06-08 20:10:45
【问题描述】:

我正在努力更好地处理来自gather 用户的pivot_longer。从源文档看来,我应该能够使用 name_pattern 或 names_sep 在单个命令中执行以下操作,但我一直无法找到可行的解决方案。

数据

id1 <- c("person1","person2","person3")
id2 <- c("1001","1002","1003")
id3 <- c("2001","2002", "2003")
value_1 <- c(10,50,100)
value_2 <- c(20,200, 2000)
status_1 <- c("OK","BAD","GOOD")
status_2 <- c("AWFUL","EXCELLENT","AVERAGE")

df <- data.frame(id1,id2,id3,value_1,value_2,status_1,status_2)

预期输出:

      id1  id2  id3 gradeLevel    status value
1 person1 1001 2001          1        OK    10
2 person1 1001 2001          2     AWFUL    20
3 person2 1002 2002          1       BAD    50
4 person2 1002 2002          2 EXCELLENT   200
5 person3 1003 2003          1      GOOD   100
6 person3 1003 2003          2   AVERAGE  2000

我可以通过 gather 语句和一些额外的行来实现这一点:

df %>% 
  gather(key, value,-id1, -id2,-id3) %>% 
  separate(key, c('cat', 'gradeLevel'),sep ="_") %>% 
  distinct() %>% 
  spread(cat,value)

有没有办法用pivot_longer 简化这个?我认为 names_pattern 很有希望,但我在使用正则表达式时遇到了困难。我的大部分尝试都是尝试组合不同类型的列(双倍和因子)

df %>%
  pivot_longer(cols = value_1:status_2, names_to = c('col', '.value'), names_pattern = "(.*)_(.)")

【问题讨论】:

    标签: r dplyr tidyverse tidyr


    【解决方案1】:

    您可以使用以下解决方案。在这种情况下,我们创建 2 个捕获组。 .value 实际上在这里所做的是为 pivot_longer 定义名称的一部分,其中包含我们要测量的值的名称。这里下划线的左侧是值valuestatus。下划线的右侧实际上是我们第二个捕获组的结果,定义了id。并且需要注意的是names_to参数的长度应该和names_pattern或者names_sep中的捕获组的数量一样。

    library(tidyr)
    
    df %>%
      pivot_longer(!c(id1, id2, id3), names_to = c(".value", "gradelevel"), 
                   names_pattern = "(\\w+)_(\\d+)")
    
    # A tibble: 6 x 6
      id1     id2   id3   gradelevel value status   
      <chr>   <chr> <chr> <chr>      <dbl> <chr>    
    1 person1 1001  2001  1             10 OK       
    2 person1 1001  2001  2             20 AWFUL    
    3 person2 1002  2002  1             50 BAD      
    4 person2 1002  2002  2            200 EXCELLENT
    5 person3 1003  2003  1            100 GOOD     
    6 person3 1003  2003  2           2000 AVERAGE  
    

    【讨论】:

    • 非常有帮助。为了检查我的理解,我可以替换为“(.+)_(.+)”以允许查找下划线两侧的任何单词或数字,对吗?
    • 是的,在这种情况下会产生相同的结果。这 (.*)_(.*) 也有效。但是还有一些非常复杂的情况,您需要专门为单词数或任何其他字符定义捕获组。
    • 有道理,欣赏。
    猜你喜欢
    • 2021-12-29
    • 1970-01-01
    • 2022-11-10
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    • 2015-01-22
    • 2021-09-07
    相关资源
    最近更新 更多