基于列名和行名合并多个R数据框并按列分组展示求助
问题:按列名分组合并多个R数据框的同名列,保留所有行名
我有3个R数据框df1、df2、df3,需要基于列名和行名将各数据框中的相同列提取出来,合并为新的分组数据框(如将所有数据框的C1列合并为包含C1.DF1、C1.DF2、C1.DF3列的新数据框,保留所有行名)。尝试使用reshape包的merge_recurse函数,但该函数是逐行合并,无法实现列并排的需求,请求帮助实现目标输出。
目标输出示例
C1.DF1 C1.DF2 C1.DF3 G1 0 1 NA G2 3 NA 1 G3 3 NA 2 G4 NA 0 NA G5 NA 2 NA G6 NA NA 4 C2.DF1 C2.DF2 C2.DF3 G1 0 2 NA G2 1 NA 1 G3 1 NA 3 G4 NA 2 NA G5 NA 1 NA G6 NA NA 3 C3.DF1 C3.DF2 C3.DF3 G1 1 3 NA G2 2 NA 1 G3 1 NA 4 G4 NA 2 NA G5 NA 3 NA G6 NA NA 2
数据框定义代码
df1 <- data.frame(C1=c(0,3,3),C2=c(0,1,1),C3=c(1,2,1),row.names = c("G1","G2","G3")) df2 <- data.frame(C1=c(1,0,2),C2=c(2,2,1),C3=c(3,2,3),row.names = c("G1","G4","G5")) df3 <- data.frame(C1=c(1,2,4),C2=c(1,3,3),C3=c(1,4,2),row.names = c("G2","G3","G6")) df_list <- list(df1,df2,df3) data <- merge_recurse(df_list) # 此方法结果不符合需求,为逐行合并形式
解决方案
方法1:使用tidyverse工具链
library(tidyverse) # 1. 给每个数据框添加来源标识,并将行名转为列 df_list_named <- list(df1 = df1, df2 = df2, df3 = df3) %>% imap(~ .x %>% rownames_to_column("rowname") %>% mutate(source = .y)) # 2. 合并所有数据框并转成宽格式,生成C1.DF1这类列名 combined <- bind_rows(df_list_named) %>% pivot_wider(names_from = source, values_from = starts_with("C"), names_sep = ".") # 3. 按原列名分组,生成每个分组的数据框并恢复行名 result <- combined %>% pivot_longer(cols = -rowname, names_to = c("col", "source"), names_sep = "\\.") %>% pivot_wider(names_from = c(col, source), values_from = value) %>% split(f = str_remove(names(.)[-1], "\\..*")) %>% map(~ .x %>% column_to_rownames("rowname")) # 查看结果 result$C1 result$C2 result$C3
方法2:使用Base R实现
# 1. 给每个数据框的列添加对应后缀(DF1/DF2/DF3) df_list_renamed <- mapply(function(df, suffix) { colnames(df) <- paste0(colnames(df), ".", suffix) df }, df_list, c("DF1", "DF2", "DF3"), SIMPLIFY = FALSE) # 2. 合并所有数据框,保留所有行名 merged_all <- Reduce(function(x, y) merge(x, y, by = "row.names", all = TRUE), df_list_renamed) rownames(merged_all) <- merged_all$Row.names merged_all$Row.names <- NULL # 3. 按原列名分组提取列,生成分组数据框 col_groups <- split(colnames(merged_all), str_remove(colnames(merged_all), "\\..*")) result <- lapply(col_groups, function(g) merged_all[, g]) # 查看结果 result$C1 result$C2 result$C3
以上两种方法都能生成符合需求的分组数据框,每个分组对应原数据框的一个列名,包含来自不同数据框的同名列(带数据框后缀),且保留了所有行名。
内容的提问来源于stack exchange,提问作者Shyamili
相关产品推荐
相关产品推荐

