如何在DataFrame列块间插入对应命名的空列?
问题描述
我有如下结构的DataFrame:
Col_1 Col_X_1 Col_2 Col_X_2 ... ABC 890 AJF 341 JFH 183 DFJ 132 ...
希望在每个按末尾数字归为一组的列块(例如Col_1 & Col_X_1)之后,插入两个空列,命名为Col_Y_n和Col_Z_n(n为列块的末尾数字)。最终的DataFrame应如下所示:
Col_1 Col_X_1 Col_Y_1 Col_Z_1 Col_2 Col_X_2 Col_Y_2 Col_Z_2 ... ABC 890 AJF 341 JFH 183 DFJ 132 ...
以下是真实数据的dput输出:
structure(list(Company = c("CompanyA", "CompanyB"), Team_1 = c("NameA", "NameB"), Team_Desc_1 = c("Founder & Co-CEO", "Senior Blockchain Engineer"), Team_URL_1 = c("https://www.linkedin.com/in/NameA/", NA), Team_Ver_1 = c("unverified", NA), Team_2 = c("NameC", "NameD"), Team_Desc_2 = c("Chairman", "Senior Software Engineer" ), Team_URL_2 = c("https://www.linkedin.com/in/NameC/", NA), Team_Ver_2 = c("unverified", NA), Team_3 = c("NameE", "NameF")), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -2L), groups = structure(list( Company = c("CompanyB", "CompanyA"), .rows = structure(list( 2L, 1L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -2L), .drop = TRUE))
解决方案
方法一:使用tidyverse工具链
这套方法更简洁,适合熟悉tidyverse生态的用户:
library(tidyverse) # 加载数据并取消分组(原数据为grouped_df,先转为普通df) df <- structure(list(Company = c("CompanyA", "CompanyB"), Team_1 = c("NameA", "NameB"), Team_Desc_1 = c("Founder & Co-CEO", "Senior Blockchain Engineer"), Team_URL_1 = c("https://www.linkedin.com/in/NameA/", NA), Team_Ver_1 = c("unverified", NA), Team_2 = c("NameC", "NameD"), Team_Desc_2 = c("Chairman", "Senior Software Engineer" ), Team_URL_2 = c("https://www.linkedin.com/in/NameC/", NA), Team_Ver_2 = c("unverified", NA), Team_3 = c("NameE", "NameF")), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -2L), groups = structure(list( Company = c("CompanyB", "CompanyA"), .rows = structure(list( 2L, 1L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -2L), .drop = TRUE)) %>% ungroup() # 提取列的分组编号,Company列单独归为0组 col_groups <- tibble(col_name = colnames(df)) %>% mutate( group_num = case_when( col_name == "Company" ~ 0, TRUE ~ str_extract(col_name, "\\d+$") %>% as.integer() ) ) # 构建目标列顺序:每个分组后追加对应编号的Y、Z列 target_cols <- col_groups %>% group_by(group_num) %>% summarise(cols = list(col_name), .groups = "drop") %>% arrange(group_num) %>% mutate( add_cols = if_else(group_num != 0, list(paste0(c("Team_Y_", "Team_Z_"), group_num)), list(NULL)) ) %>% mutate(full_cols = map2(cols, add_cols, ~c(.x, .y))) %>% pull(full_cols) %>% flatten_chr() # 重新排列列并填充空列值为NA result_df <- df %>% select(all_of(target_cols)) %>% mutate(across(starts_with("Team_Y_") | starts_with("Team_Z_"), ~NA_character_)) # 查看结果 print(result_df)
方法二:Base R实现
如果偏好原生R语法,可使用以下代码:
# 加载数据并取消分组 df <- structure(list(Company = c("CompanyA", "CompanyB"), Team_1 = c("NameA", "NameB"), Team_Desc_1 = c("Founder & Co-CEO", "Senior Blockchain Engineer"), Team_URL_1 = c("https://www.linkedin.com/in/NameA/", NA), Team_Ver_1 = c("unverified", NA), Team_2 = c("NameC", "NameD"), Team_Desc_2 = c("Chairman", "Senior Software Engineer" ), Team_URL_2 = c("https://www.linkedin.com/in/NameC/", NA), Team_Ver_2 = c("unverified", NA), Team_3 = c("NameE", "NameF")), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -2L), groups = structure(list( Company = c("CompanyB", "CompanyA"), .rows = structure(list( 2L, 1L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -2L), .drop = TRUE)) %>% ungroup() # 获取列名并提取分组编号 cols <- colnames(df) group_nums <- ifelse(cols == "Company", 0, as.integer(sub(".*_(\\d+)$", "\\1", cols))) # 按分组编号排序原始列 sorted_cols <- cols[order(group_nums)] # 生成所有需要插入的空列名 insert_cols <- lapply(unique(group_nums[group_nums != 0]), function(n) { paste0(c("Team_Y_", "Team_Z_"), n) }) %>% unlist() # 构建最终列顺序 final_cols <- c() current_group <- 0 for (col in sorted_cols) { col_group <- ifelse(col == "Company", 0, as.integer(sub(".*_(\\d+)$", "\\1", col))) if (col_group != current_group && current_group != 0) { final_cols <- c(final_cols, paste0(c("Team_Y_", "Team_Z_"), current_group)) } final_cols <- c(final_cols, col) current_group <- col_group } # 补充最后一组的空列 final_cols <- c(final_cols, paste0(c("Team_Y_", "Team_Z_"), current_group)) # 创建结果DataFrame并添加空列 result_df <- df[, sorted_cols, drop = FALSE] for (col in insert_cols) { result_df[[col]] <- NA_character_ } # 调整列顺序 result_df <- result_df[, final_cols] # 查看结果 print(result_df)
内容的提问来源于stack exchange,提问作者Soph2010
相关产品推荐
相关产品推荐

