r - 如何一次性将 tidyr::pivot_longer 与 stringr::separate_rows 结合起来
问题描述
我正在尝试根据列名将数据从宽格式转换为长格式,我可以使用tidyr::pivot_longer()
. 但是,我还需要以宽格式解构特定单元格的内容——即解析其中的字符串——并沿着旋转(更长)行分离解析的组件。虽然解析和分离任务很容易完成stringr::separate_rows
,但我不知道如何在同一个镜头中结合旋转和分离过程。
数据
df <- data.frame(
id = 1:3,
blue_type1 = 110:112,
purple_type5 = 5:7,
black_type1 = 28:30,
batch_number = c("bgd | ddg | qwe",
"afp | qqw | edt",
"pqr | khp | rty")
)
df
## id blue_type1 purple_type5 black_type1 batch_number
## 1 1 110 5 28 bgd | ddg | qwe
## 2 2 111 6 29 afp | qqw | edt
## 3 3 112 7 30 pqr | khp | rty
我想要的是
转换为长格式并解包batch_number
,以便将第一个子字符串分配给长格式的第一行,将第二个子字符串分配给第二行,将第三个子字符串分配给第三行。
期望的输出
## # A tibble: 9 x 5
## id batch_number color type vals
## <dbl> <chr> <chr> <dbl> <dbl>
## 1 1 bgd blue 1 110
## 2 1 ddg purple 5 5
## 3 1 qwe black 1 28
## 4 2 afp blue 1 111
## 5 2 qqw purple 5 6
## 6 2 edt black 1 29
## 7 3 pqr blue 1 112
## 8 3 khp purple 5 7
## 9 3 rty black 1 30
我的尝试
如果我只是tidyr::pivot_longer
,我到了一半:
df %>%
pivot_longer(.,
-c(id, batch_number),
names_to = c("color", "type"),
names_pattern = "(.*)_type(.)",
values_to = "vals")
## # A tibble: 9 x 5
## id batch_number color type vals
## <int> <chr> <chr> <chr> <int>
## 1 1 bgd | ddg | qwe blue 1 110
## 2 1 bgd | ddg | qwe purple 5 5
## 3 1 bgd | ddg | qwe black 1 28
## 4 2 afp | qqw | edt blue 1 111
## 5 2 afp | qqw | edt purple 5 6
## 6 2 afp | qqw | edt black 1 29
## 7 3 pqr | khp | rty blue 1 112
## 8 3 pqr | khp | rty purple 5 7
## 9 3 pqr | khp | rty black 1 30
如果我尝试stringr::separate_rows
在此之上,我会得到不想要的输出:
## # A tibble: 27 x 5
## # Groups: id [3]
## id batch_number color type vals
## <int> <chr> <chr> <chr> <int>
## 1 1 bgd blue 1 110
## 2 1 ddg blue 1 110
## 3 1 qwe blue 1 110
## 4 1 bgd purple 5 5
## 5 1 ddg purple 5 5
## 6 1 qwe purple 5 5
## 7 1 bgd black 1 28
## 8 1 ddg black 1 28
## 9 1 qwe black 1 28
## 10 2 afp blue 1 111
## 11 2 qqw blue 1 111
## 12 2 edt blue 1 111
## 13 2 afp purple 5 6
## 14 2 qqw purple 5 6
## 15 2 edt purple 5 6
## 16 2 afp black 1 29
## 17 2 qqw black 1 29
## 18 2 edt black 1 29
## 19 3 pqr blue 1 112
## 20 3 khp blue 1 112
## 21 3 rty blue 1 112
## 22 3 pqr purple 5 7
## 23 3 khp purple 5 7
## 24 3 rty purple 5 7
## 25 3 pqr black 1 30
## 26 3 khp black 1 30
## 27 3 rty black 1 30
我怎么能合并运行separate_rows
时的操作pivot_longer
?有没有一种优雅的方式来完成这样的任务?基本上我正在寻找tidyverse
解决方案,但也会对其他方法感到满意。
解决方案
也许有一个更短更优雅的解决方案,但同时你可以试试这个。基本思想是
- 在调用之前添加批次标识符 (
batch
) (by )id
tidyr::separate_rows
- 过滤后
tidyr::separate_rows
obsbatch_number
和batch
标识符相等的 obs。对于这最后一步,我首先batch_number
使用转换为一个因子forcats::fct_inorder
,然后转换为一个数字,它给我它的位置batch_number
然后可以与batch
标识符匹配
set.seed(42)
df <- data.frame(
id = 1:3,
blue_type1 = 110:112,
purple_type5 = 5:7,
black_type1 = 28:30,
batch_number = c("bgd | ddg | qwe",
"afp | qqw | edt",
"pqr | khp | rty")
)
library(dplyr)
library(tidyr)
library(forcats)
df %>%
pivot_longer(-c(id, batch_number)) %>%
group_by(id) %>%
mutate(batch = row_number()) %>%
separate_rows(batch_number) %>%
filter(batch == as.numeric(forcats::fct_inorder(batch_number)))
#> # A tibble: 9 x 5
#> # Groups: id [3]
#> id batch_number name value batch
#> <int> <chr> <chr> <int> <int>
#> 1 1 bgd blue_type1 110 1
#> 2 1 ddg purple_type5 5 2
#> 3 1 qwe black_type1 28 3
#> 4 2 afp blue_type1 111 1
#> 5 2 qqw purple_type5 6 2
#> 6 2 edt black_type1 29 3
#> 7 3 pqr blue_type1 112 1
#> 8 3 khp purple_type5 7 2
#> 9 3 rty black_type1 30 3
推荐阅读
- github - GitHub 提交守门人
- java - 在目标之前在 Java Eclipse Maven 中执行 jar
- typescript - 如何使用 ng-2 智能表在创建和编辑时自动完成
- laravel - Laravel Auth 重置密码功能视图不起作用
- php - MySQL查询无结果
- abap - 有没有办法检查 RFC 是否存在于 SAP 系统中
- ios - 在 swift (iOS) 中的文本字段内添加前缀
- javascript - 将字符串转换为日期而不考虑时区
- kubernetes - OpenEBS 是否支持 Jiva Volumes 的 ReadOnlyMany 选项?
- php - 使用 PHP 使用包含电子邮件地址的查询字符串验证 url