You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:50:42