当变量由多个部分组成时,将 tibble 转换为长格式
Convert tibble to long form when the variables consist of several parts
我有这样的数据
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) 两部分,这应该成为长版本中的新变量table 如下。
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
效果很失望
欢迎任何提示。
我们可以通过几种方式做到这一点 - 即首先重塑为 'long' 格式 pivot_longer
排除 'id' 列,然后仅 separate
[=通过将 sep
指定为正则表达式环视,即(因为只有一个小写字母),将 27=] 列分成两列,在第一次出现该字母后拆分 ((?<=[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 = "^(.)(.)_(.*)")
我知道以前有人问过这个问题,但我找不到好的重复目标。同时,如果您指定正则表达式来区分列名的 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
如果您在实践中有不同的列名,请根据需要调整正则表达式,但这会将它们分开,以便第一部分来自字符串开头的单个小写字母,第二部分来自单个数字在字符串的末尾。
我有这样的数据
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) 两部分,这应该成为长版本中的新变量table 如下。
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
效果很失望
欢迎任何提示。
我们可以通过几种方式做到这一点 - 即首先重塑为 'long' 格式 pivot_longer
排除 'id' 列,然后仅 separate
[=通过将 sep
指定为正则表达式环视,即(因为只有一个小写字母),将 27=] 列分成两列,在第一次出现该字母后拆分 ((?<=[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 = "^(.)(.)_(.*)")
我知道以前有人问过这个问题,但我找不到好的重复目标。同时,如果您指定正则表达式来区分列名的 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
如果您在实践中有不同的列名,请根据需要调整正则表达式,但这会将它们分开,以便第一部分来自字符串开头的单个小写字母,第二部分来自单个数字在字符串的末尾。