【问题标题】:`pivot_longer` operation with different naming schemes具有不同命名方案的“pivot_longer”操作
【发布时间】:2020-09-22 14:57:58
【问题描述】:

我有一个df 的形式:

df <- tibble(
  id = c(1,2,3),
  x02val_a = c(0,1,0),
  x03val_a = c(1,0,0),
  x04val_a = c(0,1,1),
  x02val_b = c(0,2,0),
  x03val_b = c(1,3,0),
  x04val_b = c(0,1,2),
  age02 = c(1,2,3),
  age03 = c(2,3,4),
  age04 = c(3,4,5)
)

我想把它变成整洁的格式,比如:

# A tibble: 9 x 5
     id year    val_a   val_b   age
  <dbl> <chr>   <dbl>   <dbl>   <dbl>
1     1 02          0       0       1
2     1 03          1       2       2
...

here 的答案适用于更简单的命名方案。然而,由于我的真实数据集中存在命名方案,我很难定义一个匹配所有模式的正则表达式。

到目前为止,我的尝试都错过了一个或其他方案。我可以获取变量名在前,年份在后的那个 (age02),或者类型和年份在前,名称在后的那个 (x02var),但不能同时获取。

有没有办法用 a) 正则表达式来做到这一点?或 b) pivot_longer 调用的一些组合或参数化?

我知道总是有可能在最后使用左连接来做到这一点,正如我所描述的here


我试图用两个组来定义正则表达式(因为这些组不是严格连续的[意思是:左,右],这导致我):

df %>%
  pivot_longer(-id,names_to = c('.value', 'year'),names_pattern = '([a-z]+(\\d+)[a-z]+_[a-z])')

【问题讨论】:

    标签: r tidyr


    【解决方案1】:

    让我们试试。似乎这种名称模式有效:

    > df %>% 
        pivot_longer(-id,
                      names_to = c('.value', 'year','.value'),
                      names_pattern = '([a-z]+)(\\d+)([a-z_]*)')
    # A tibble: 9 x 5
         id year  xval_a xval_b   age
      <dbl> <chr>  <dbl>  <dbl> <dbl>
    1     1 02         0      0     1
    2     1 03         1      1     2
    3     1 04         0      0     3
    4     2 02         1      2     2
    5     2 03         0      3     3
    6     2 04         1      1     4
    7     3 02         0      0     3
    8     3 03         0      0     4
    9     3 04         1      2     5
    

    【讨论】:

    • 定义一个包含三个组的正则表达式的想法,其中一些可能在某些名称中丢失,对我有用。谢谢
    【解决方案2】:

    这有点迂回,但由于名称样式不一致,您可能首先重命名列以匹配更简单的模式。您的姓名中有 3 条可能的信息,但(至少在您的示例中)每列只有其中 2 条。

    相关的部分是:

    • "[a-z_]" 的多个连续匹配,出现在“x”之后或2 位数字之后。无论其中哪一个出现,都将移至名称的开头;无论 哪个存在,都不会返回任何内容,也不会占用任何空间。
    • 2 位数字,移到末尾。

    pivot_longer".value" 选项可以根据这种更简洁的模式在一个步骤中为您提供列名称。应该足够微不足道以根据需要调整模式,例如以适应不同的位数。

    library(dplyr)
    library(tidyr)
    
    df %>%
      rename_all(stringr::str_replace, "x?([a-z_]*)(\\d{2})([a-z_]*)", "\\1\\3\\2") %>%
      pivot_longer(-id, names_to = c(".value", "year"), names_pattern = "([a-z_]+)(\\d{2})")
    #> # A tibble: 9 x 5
    #>      id year  val_a val_b   age
    #>   <dbl> <chr> <dbl> <dbl> <dbl>
    #> 1     1 02        0     0     1
    #> 2     1 03        1     1     2
    #> 3     1 04        0     0     3
    #> 4     2 02        1     2     2
    

    【讨论】:

      猜你喜欢
      • 2011-02-04
      • 2021-05-02
      • 1970-01-01
      • 2020-02-15
      • 1970-01-01
      • 2011-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多