Pivot_longer 对 names_pattern 中的两位数使用正则表达式

Pivot_longer with regex for two-digit numbers in names_pattern

我有一个大型宽格式数据集,其中包含在多个波中测量的许多变量,其中每个变量波组合(例如年龄 1、年龄 2、年龄 3、年龄 4)有一列,还有一些时间- 固定变量(例如 ID、性别)。旋转后,我希望每个变量都由一个列表示,旁边是一个新的 'wave' 列。

它的工作几乎完美,只是我无法在同一列中表示第 1-9 波和第 10-13 波。

df <- data.frame(
  ID = c(10001,10002),
  Sex = c(1,2),
  Age1 = c(73,25),
  Age2 = c(74,26),
  Age3=c(75,27),
  Age4 = c(76,28),
  Age5 = c(77,29),
  Age6=c(78,30),
  Age7 = c(79,31),
  Age8 = c(80,31),
  Age9=c(81,33),
  Age10=c(82,34),
  Age11 = c(83,35),
  Age12 = c(84,36),
  Age13=c(85,37)
)

names_test<-names(df) 
no_numb<-grep("*[A-Za-z]$", names_test) #to identify all the column names ending with a letter, which I do NOT want to pivot into longer form

df_long<-pivot_longer(df,cols = !no_numb, names_to = c('.value',"wave"),
                  names_pattern = "(.*)(\d+)$")

长数据输出:

> df_long
# A tibble: 20 x 5
      ID   Sex wave    Age  Age1
   <dbl> <dbl> <chr> <dbl> <dbl>
 1 10001     1 1        73    83
 2 10001     1 2        74    84
 3 10001     1 3        75    85
 4 10001     1 4        76    NA
 5 10001     1 5        77    NA
 6 10001     1 6        78    NA
 7 10001     1 7        79    NA
 8 10001     1 8        80    NA
 9 10001     1 9        81    NA
10 10001     1 0        NA    82
11 10002     2 1        25    35
12 10002     2 2        26    36
13 10002     2 3        27    37
14 10002     2 4        28    NA
15 10002     2 5        29    NA
16 10002     2 6        30    NA
17 10002     2 7        31    NA
18 10002     2 8        31    NA
19 10002     2 9        33    NA
20 10002     2 0        NA    34

如您所见,有一列 Age,其中包含波 1-9 的值,还有一列 Age1,其中包含 1、2、3 和 0 的值(即 Age10、Age11、Age12 ,13 岁)。 我假设这里的问题是 names_to 参数或 names_pattern 参数。任何帮助将不胜感激!

.*是贪心的,所以取最大匹配字符串。你可以使用

pivot_longer(df,cols = !no_numb, names_to = c('.value',"wave"),
                  names_pattern = "(Age)(\d+)$")

或者通过添加 ?

使其不贪心
pivot_longer(df,cols = !no_numb, names_to = c('.value',"wave"),
                  names_pattern = "(.*?)(\d+)$")

这个returns

# A tibble: 26 x 4
      ID   Sex wave    Age
   <dbl> <dbl> <chr> <dbl>
 1 10001     1 1        73
 2 10001     1 2        74
 3 10001     1 3        75
 4 10001     1 4        76
 5 10001     1 5        77
 6 10001     1 6        78
 7 10001     1 7        79
 8 10001     1 8        80
 9 10001     1 9        81
10 10001     1 10       82
# ... with 16 more rows

我们也可以将 names_sep 与正则表达式一起使用

library(tidyr)
 pivot_longer(df, cols = starts_with('Age'), 
   names_to = c(".value", "wave"), names_sep = "(?<=[a-z])(?=[0-9])")
# A tibble: 26 × 4
      ID   Sex wave    Age
   <dbl> <dbl> <chr> <dbl>
 1 10001     1 1        73
 2 10001     1 2        74
 3 10001     1 3        75
 4 10001     1 4        76
 5 10001     1 5        77
 6 10001     1 6        78
 7 10001     1 7        79
 8 10001     1 8        80
 9 10001     1 9        81
10 10001     1 10       82
# … with 16 more rows