R语言多列pivot_longer优化方案求助
优化宽格式转长格式的R代码方案
问题场景
现有如下数据集:
library(tidyr) # 创建数据集 data <- data.frame( id = 1:12, f51a_01 = c(1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3), f51a_02 = c(1, 2, 3, 6, 1, 2, 3, 4, 5, 6, 1, 6), f51b_01 = c(1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 3), f51b_02 = c(1, 2, 2, 6, 6, 6, 6, 6, 6, 6, 1, 6) )
需要转换为以下长格式输出:
id var var_01 var_02 1 f51a 1 1 1 f51b 1 1 2 f51a 1 2 2 f51b 1 2 3 f51a 1 3 3 f51b 2 2 4 f51a 1 6 4 f51b 1 6 5 f51a 2 1 5 f51b 1 6 6 f51a 2 2 6 f51b 1 6 7 f51a 2 3 7 f51b 1 6 8 f51a 2 4 8 f51b 1 6 9 f51a 2 5 9 f51b 1 6 10 f51a 2 6 10 f51b 1 6 11 f51a 3 1 11 f51b 3 1 12 f51a 3 6 12 f51b 3 6
原方案分析
原方案通过两次pivot_longer分别处理_01和_02结尾的列,再通过left_join合并,虽然可行,但存在重复操作,对于大数据集效率较低:
data%>% select(id, matches("f51[a-z]_01"))%>% pivot_longer(cols = -id, names_to = "var", values_to = "var_01")%>% mutate(var = str_extract(var, "f51[a-z]"))%>% left_join(data%>% select(id, matches("f51[a-z]_02"))%>% pivot_longer(cols = -id, names_to = "var", values_to = "var_02")%>% mutate(var = str_extract(var, "f51[a-z]")))
优化方案
利用tidyr::pivot_longer的names_pattern参数,一次性拆分列名并转换格式,无需多次操作和合并:
library(tidyr) library(dplyr) data %>% pivot_longer( cols = starts_with("f51"), # 选择所有以f51开头的列 names_to = c("var", ".value"), # var存储前缀,.value指定后缀作为新列名 names_pattern = "(f51[a-z])_(0\\d)" # 正则拆分:捕获组1为var,捕获组2为列后缀 ) %>% rename_with(~paste0("var_", .), matches("0\\d")) # 将01/02重命名为var_01/var_02
方案说明
names_pattern正则拆分:通过正则表达式(f51[a-z])_(0\\d),将列名拆分为两个部分:f51a/f51b(存入var列)和01/02(作为新列的名称,由.value参数指定)。- 一步完成转换:一次
pivot_longer操作就完成了宽转长和列映射,避免了重复的select、pivot和join操作,代码更简洁,执行效率更高。 - 列重命名:最后通过
rename_with将01/02列重命名为var_01/var_02,匹配期望输出格式。
执行上述代码后,输出结果与期望完全一致。
内容的提问来源于stack exchange,提问作者Waschi Waschoi
相关产品推荐
相关产品推荐

