r语言 - 当变量由几个部分组成时,将 tibble 转换为长格式



我有这样的数据

library(tidyverse)
df = tribble(
~id, ~a1, ~a2, ~a3, ~b1, ~b2, ~b3, ~c1, ~c2, ~c3,
1,   1,   4,   7,  11,  14,  17,  21,  24,  27,
2,   2,   5,   8,  12,  15,  18,  22,  25,  28,
3,   3,   6,   8,  13,  16,  19,  23,  26,  29,
)

我想将其转换为长格式,其中变量名称包含两部分名称(a,b,c)和数字(1,2,3),它们应该成为表格长版本中的新变量,如下所示。

id name nr data
1   1    a  1    1
2   2    a  1    2
3   3    a  1    3
4   1    a  2    4
5   2    a  2    5
6   3    a  2    6
7   1    a  3    7
8   2    a  3    8
9   3    a  3    8
10  1    b  1   11
11  2    b  1   12
12  3    b  1   13
13  1    b  2   14
14  2    b  2   15
15  3    b  2   16
16  1    b  3   17
17  2    b  3   18
18  3    b  3   19
19  1    C  1   21
20  2    C  1   22
21  3    C  1   23
22  1    C  2   24
23  2    C  2   25
24  3    C  2   26
25  1    C  3   27
26  2    C  3   28
27  3    C  3   29

可以简单地使用dplyr包中的函数来完成吗?我试过pivot_longer效果令人失望。

欢迎任何提示。

我知道这个问题以前有人问过,但我找不到一个好的重复目标。同时,如果您指定正则表达式来区分列名的name部分和nr部分,则可以在一次函数调用中执行此操作:


df %>%
pivot_longer(-id, names_to = c("name", "nr"), 
values_to = "data", 
names_pattern = "(^[a-z])(\d$)")
#> # A tibble: 27 × 4
#>       id name  nr     data
#>    <dbl> <chr> <chr> <dbl>
#>  1     1 a     1         1
#>  2     1 a     2         4
#>  3     1 a     3         7
#>  4     1 b     1        11
#>  5     1 b     2        14
#>  6     1 b     3        17
#>  7     1 c     1        21
#>  8     1 c     2        24
#>  9     1 c     3        27
#> 10     2 a     1         2
#> # … with 17 more rows

如果您在实践中有不同的列名,请根据需要调整正则表达式,但这会将它们分开,以便第一部分来自字符串开头的单个小写字母,第二部分来自字符串末尾的单个数字。

我们可以通过几种方式做到这一点 - 即首先将pivot_longer排除"id"列重新塑造为"long"格式,然后通过将sep指定为正则表达式查找separate"name"列,即(因为只有一个小写字母),在字母第一次出现后拆分((?<=[a-z]))

library(dplyr)
library(tidyr)
df %>% 
pivot_longer(cols = -id, names_to = 'name', values_to = 'data') %>%
separate(name, into = c("name", 'nr'), sep = "(?<=[a-z])")

-输出

A tibble: 27 × 4
id name  nr     data
<dbl> <chr> <chr> <dbl>
1     1 a     1         1
2     1 a     2         4
3     1 a     3         7
4     1 b     1        11
5     1 b     2        14
6     1 b     3        17
7     1 c     1        21
8     1 c     2        24
9     1 c     3        27
10     2 a     1         2
# … with 17 more rows

或者另一种选择是在列名中附加后缀,然后使用pivot_longer

library(stringr)
df %>% 
rename_with(~ str_c(., "_data"), -id) %>% 
pivot_longer(cols = -id, names_to = c("name", "nr", ".value"), 
names_pattern = "^(.)(.)_(.*)")

相关内容

  • 没有找到相关文章

最新更新