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

使用tidyr的crossing函数合并数据框时自动修复重复列名

使用tidyr::crossing合并带重复列名的数据框时自动添加后缀

问题说明

想要用crossing函数合并两个存在重复列名的数据框,期望为重复列自动添加“_数据框名称”的后缀,避免列名冲突。

原始数据

> df1
  person V1 V2 V3
1      A  1  3  3
2      B  4  4  5
3      C  2  1  1
> df2
  V2 V3
1  2  5
2  1  6
3  1  2

当前代码的问题

运行以下代码会生成重复列名的结果:

library(tidyr)
crossing(df1, df2, .name_repair = "minimal")
#> # A tibble: 9 × 6
#>   person    V1    V2    V3    V2    V3
#>   <chr>  <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A          1     3     3     1     2
#> 2 A          1     3     3     1     6
#> 3 A          1     3     3     2     5
#> 4 B          4     4     5     1     2
#> 5 B          4     4     5     1     6
#> 6 B          4     4     5     2     5
#> 7 C          2     1     1     1     2
#> 8 C          2     1     1     1     6
#> 9 C          2     1     1     2     5

期望输出

需要得到列名唯一的结果,重复列自动添加对应数据框的后缀:

person V1 V2_df1 V3_df1 V2_df2 V3_df2
1      A  1      3      3      1      2
2      A  1      3      3      1      6
3      A  1      3      3      2      5
4      B  4      4      5      1      2
5      B  4      4      5      1      6
6      B  4      4      5      2      5
7      C  2      1      1      1      2
8      C  2      1      1      1      6
9      C  2      1      1      2      5

可复现代码

df1 <- structure(list(person = c("A", "B", "C"), V1 = c(1, 4, 2), V2 = c(3, 
4, 1), V3 = c(3, 5, 1)), class = "data.frame", row.names = c(NA, 
-3L))

df2 <- structure(list(V2 = c(2, 1, 1), V3 = c(5, 6, 2)), class = "data.frame", row.names = c(NA, 
-3L))

解决方案

方法1:提前重命名重复列后合并

先识别重复列名,给每个数据框的重复列添加对应后缀,再执行crossing:

library(tidyverse)

# 获取两个数据框的共同列名
common_cols <- intersect(names(df1), names(df2))

# 给df1的重复列添加_df1后缀
df1_renamed <- df1 %>% 
  rename_with(~ paste0(., "_df1"), all_of(common_cols))

# 给df2的重复列添加_df2后缀
df2_renamed <- df2 %>% 
  rename_with(~ paste0(., "_df2"), all_of(common_cols))

# 执行笛卡尔积合并
crossing(df1_renamed, df2_renamed)

方法2:自定义.name_repair函数

利用crossing的.name_repair参数,自定义函数自动为重复列添加后缀:

library(tidyr)

custom_name_repair <- function(col_names) {
  cols_df1 <- names(df1)
  cols_df2 <- names(df2)
  
  new_names <- map_chr(col_names, function(col) {
    # 判断当前列是否是重复列
    if (col %in% cols_df1 && col %in% cols_df2) {
      # 由于crossing先按输入顺序排列列,前半部分来自df1,后半来自df2
      col_idx <- which(col_names == col)
      if (col_idx <= length(cols_df1)) {
        paste0(col, "_df1")
      } else {
        paste0(col, "_df2")
      }
    } else {
      col
    }
  })
  # 确保名称唯一(防止极端情况)
  make.unique(new_names, sep = "")
}

# 使用自定义名称修复函数
crossing(df1, df2, .name_repair = custom_name_repair)

方法3:利用列表批量处理重命名

将数据框放入列表,结合imap批量添加后缀,再通过!!!展开执行crossing:

library(tidyverse)

# 构造带名称的列表,批量重命名重复列
df_list <- list(df1 = df1, df2 = df2) %>% 
  imap(~ rename_with(.x, 
                     ~ ifelse(.x %in% intersect(names(df1), names(df2)), 
                              paste0(.x, "_", .y), .x)))

# 展开列表并执行crossing
crossing(!!!df_list)

内容的提问来源于stack exchange,提问作者Quinten

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:55:21