R语言如何基于列名分组将数据框拆分为两个独立数据框
问题说明
现有如下构造的tibble对象:
my_tibble <- tibble(`A` = c(1,2), `B` = c(2,1), `C` = c(2,2), `D` = c(1,3), `E` = c(2,3), `F` = c(5,2)) %>% mutate(`LIST 1` = rowSums(.[1:4]), `LIST 2` = rowSums(.[5:6])) %>% select(`LIST 1`,A:D,`LIST 2`,E:F)
数据中A-D列归属LIST 1分组,E、F列归属LIST 2分组,需要通过自动化方法将数据框拆分为两个独立数据框,目标输出结构如下:
list1df <- tibble(`A` = c(1,2), `B` = c(2,1), `C` = c(2,2), `D` = c(1,3)) %>% mutate(`LIST 1` = rowSums(.[1:4])) %>% select(`LIST 1`,A:D) list2df <- tibble(`E` = c(2,3), `F` = c(5,2)) %>% mutate(`LIST 2` = rowSums(.[1:2])) %>% select(`LIST 2`,E:F)
注:原示例代码中rowSums(.[1,2])为笔误,该写法仅提取第1行第2列的单个值,无法正确计算行和,修正为.[1:2]才能取前两列完成计算。
实现方案
核心逻辑是自动识别LIST x格式的分组列,按列的排列顺序匹配每个分组对应的下属字段,无需手动硬编码列范围,后续新增分组也可以直接复用代码。
方案1:基础R+dplyr实现
library(dplyr) library(tibble) # 提取所有分组列名称 list_cols <- grep("^LIST\\s+\\d+$", names(my_tibble), value = TRUE) split_res <- list() for (i in seq_along(list_cols)) { # 定位当前分组列位置 curr_pos <- which(names(my_tibble) == list_cols[i]) # 定位下一个分组列位置,最后一个分组取总列数+1 next_pos <- if (i == length(list_cols)) ncol(my_tibble) + 1 else which(names(my_tibble) == list_cols[i+1]) # 提取当前分组的所有列:分组列 + 两个分组列之间的下属字段 split_res[[list_cols[i]]] <- my_tibble[, c(curr_pos, (curr_pos + 1):(next_pos - 1))] } # 导出为独立数据框 list1df <- split_res[["LIST 1"]] list2df <- split_res[["LIST 2"]]
方案2:tidyverse精简写法
library(dplyr) library(tibble) # 给每一列标记所属分组 col_tag <- vector("character", ncol(my_tibble)) current_tag <- NA_character_ for (i in seq_along(col_tag)) { nm <- names(my_tibble)[i] if (grepl("^LIST\\s+\\d+$", nm)) current_tag <- nm col_tag[i] <- current_tag } # 按列标签批量拆分 split_res <- split.default(my_tibble, col_tag) # 导出为独立数据框 list1df <- split_res$`LIST 1` list2df <- split_res$`LIST 2`
两种方法输出的结果和目标结构完全一致,只要列排列保持「分组列+对应下属字段」的规则,不管后续新增多少个LIST分组,都不需要修改代码逻辑就能自动完成拆分。
内容的提问来源于stack exchange,提问作者szaki
相关产品推荐
相关产品推荐

