在 R 中使用 pivot_longer 旋转多组列

Pivoting multiple sets of columns using pivot_longer in R

我想旋转数据框中的多组变量。我的数据如下所示:

require(dplyr)
require(tidyr)
x_1=rnorm(10,0,1)
x_2=rnorm(10,0,1)
x_3=rnorm(10,0,1)
y_1=rnorm(10,0,1)
y_2=rnorm(10,0,1)
aid=rep(1:5,2)
data=data.frame(aid, x_1,x_2,y_1,y_2)

> data
   aid         x_1        x_2         y_1         y_2
1    1 -0.82305819  0.9366731  0.95419200  2.29544019
2    2  0.64424320 -0.2807793  0.51303834  0.02560463
3    3 -1.11108822 -0.2475625  0.05747951 -0.51218368
4    4 -1.04026895 -0.4138653  0.57751999  0.60942652
5    5  1.29097040 -1.7829966  1.59940532  0.75868562
6    1 -0.57845406 -1.0002074  0.04302291  0.86766265
7    2  0.08996163 -0.7949632 -2.10422124 -0.43432995
8    3  0.14331978  0.4203010 -1.12748270  0.14484670
9    4 -0.25207187  1.5559295  0.23621422 -0.04719046
10   5 -0.25617731  0.6241852 -1.21131110  1.02236458

我想分别转换 x 和 y 变量。我使用以下代码行来做到这一点。

data2 = data %>% reshape(.,direction = "long",
                varying = list(c('x_1','x_2'),
                               c('y_1','y_2')),
                v.names = c("x",'y'))

我需要将其推广到任意数量的列。这意味着,在此示例中,x 和 y 各有 2 列。但是对于另一个数据集,它可能会有所不同。如果有更多列,则很难在 varying 参数下键入所有内容。

为了避免在旋转时指定列,我尝试了以下代码:

data1 <- data%>% pivot_longer(!aid, names_to = c("id"), names_pattern = "(.)(.)")

但是它给出了这个错误:

Error: `regex` should define 1 groups;  found.

谁能帮我解决这个问题?

谢谢。

匹配模式两边的方括号表示我们将该模式作为一个组捕获。在下面的代码中,我们捕获一个或多个 lower-case 字母 ([a-z]+) 后跟一个 _ (不在括号内,因此它被删除)并且第二个捕获组匹配一个或更多数字(\d+),这将与 names_to 的相应值匹配 - 即 .value 表示列的值,因此我们得到列 'x' 和'y' 带有值,第二个将是一个新的列名,它返回列名的后缀数字,即 'time'

library(tidyr)
pivot_longer(data, cols = -aid, names_to = c(".value", "time"), 
    names_pattern = "^([a-z]+)_(\d+)")

-输出

# A tibble: 20 × 4
     aid time        x       y
   <int> <chr>   <dbl>   <dbl>
 1     1 1     -0.823   0.954 
 2     1 2      0.937   2.30  
 3     2 1      0.644   0.513 
 4     2 2     -0.281   0.0256
 5     3 1     -1.11    0.0575
 6     3 2     -0.248  -0.512 
 7     4 1     -1.04    0.578 
 8     4 2     -0.414   0.609 
 9     5 1      1.29    1.60  
10     5 2     -1.78    0.759 
11     1 1     -0.578   0.0430
12     1 2     -1.00    0.868 
13     2 1      0.0900 -2.10  
14     2 2     -0.795  -0.434 
15     3 1      0.143  -1.13  
16     3 2      0.420   0.145 
17     4 1     -0.252   0.236 
18     4 2      1.56   -0.0472
19     5 1     -0.256  -1.21  
20     5 2      0.624   1.02  

在 OP 的代码中,有两组((.)(.))并且 names_to 中只有一个元素,因此它随着存在 _ 在 'x'、'y' 和数字之间。此外,默认情况下,names_pattern 将处于正则表达式模式,因此某些字符处于 metacharacter 模式,即 . 表示任何 character 而不是文字 .

在这种情况下,names_sepnames_pattern 的便捷替代方法,因为列名已经由 _:

分隔
library(dplyr)
library(tidyr)
data %>%
  pivot_longer(-aid,
               names_to =c(".value","time"),
               names_sep ="_"
               )
     aid time       x         y
   <int> <chr>  <dbl>     <dbl>
 1     1 1      1.08  -1.49    
 2     1 2      0.871  0.449   
 3     2 1     -1.01  -0.577   
 4     2 2      1.23  -0.0890  
 5     3 1     -0.905 -0.289   
 6     3 2      1.16  -0.380   
 7     4 1     -0.316 -0.446   
 8     4 2      0.902  1.05    
 9     5 1     -0.908  1.36    
10     5 2     -0.558 -1.57    
11     1 1     -0.383  1.22    
12     1 2      0.704  0.000539
13     2 1      0.595 -0.668   
14     2 2     -0.461  1.46    
15     3 1      2.00  -0.365   
16     3 2     -1.14   0.150   
17     4 1     -2.13  -0.827   
18     4 2      0.642 -0.798   
19     5 1      0.397 -0.0143  
20     5 2      0.981  1.79