R语言合并两个数据框如何实现列按原顺序交替排列
问题说明
现有两个R数据框:
library(tibble) df1 <- tibble(b = 1:4, a = 1:4, c = 1:4) df2 <- tibble(b_B = 1:4, a_A = 1:4, c_C = 1:4)
两个数据框的内容如下:
> df1 # A tibble: 4 x 3 b a c <int> <int> <int> 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 > df2 # A tibble: 4 x 3 b_B a_A c_C <int> <int> <int> 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
需求为合并两个数据框,保留df1的原有列位置顺序,将df2的列与df1的对应列交替插入排布,期望输出如下:
b b_B a a_A c c_C 1 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3 3 3 3 4 4 4 4 4 4 4
之前尝试用gtools::mixedsort()按列名排序,会按字母顺序重排所有列,打乱df1原有的b-a-c列顺序,得到a a_A b b_B c c_C的错误结果。
解决方案
核心逻辑是不要全局排序列名,而是以df1的原始列顺序为基准,依次匹配df2中对应的关联列,按「df1列、对应df2列」的顺序拼接得到最终的列顺序,再重排合并后的数据框即可。
tidyverse 实现
library(tidyverse) df_result <- bind_cols(df1, df2) %>% # 按df1的列顺序,逐次匹配df2中对应前缀的列,交错组合 select(!!!map(names(df1), ~c(.x, starts_with(paste0(.x, "_")))))
运行结果完全符合预期:
# A tibble: 4 x 6 b b_B a a_A c c_C <int> <int> <int> <int> <int> <int> 1 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3 3 3 3 4 4 4 4 4 4 4
该写法不依赖df2本身的列顺序,只要df2的列名以df1的列名加下划线为前缀,就能自动匹配,通用性更强。
base R 实现
如果不想加载额外包,可以用base R完成同样操作:
df_merged <- cbind(df1, df2) # 逐一生成交错的列对 col_order <- unlist(lapply(names(df1), function(col) { c(col, grep(paste0("^", col, "_"), names(df2), value = TRUE)) })) df_result <- df_merged[, col_order]
原方案问题说明
gtools::mixedsort()的作用是对字符向量做混合排序(即正确识别字符串中的数字大小排序),本质还是全局排序,会按照字母优先级排列所有列名,完全忽略df1原本的列顺序,因此无法满足保留df1原始列位置的需求。
内容的提问来源于stack exchange,提问作者TarJae
相关产品推荐
相关产品推荐

