如何根据对应次数高效重复并合并数据框的列?
如何根据对应次数高效重复并合并数据框的列?
嘿,完全懂你手动处理70列的崩溃!没必要一个个敲,这里有两个高效又优雅的解法,帮你一次性搞定需求——按照df2$n-1的次数重复df1的对应列,并且自动跳过n=1的列:
方法一:Base R 原生解法(无需额外包)
这个方法用原生函数就能实现,还能保证列名匹配不出错:
# 先确保df2的name顺序和df1的列名完全对应(防止顺序不一致导致匹配错误) df2 <- df2[match(colnames(df1), df2$name), ] # 遍历每一列,生成需要重复的列列表 repeat_columns <- lapply(seq_len(ncol(df1)), function(col_index) { repeat_times <- df2$n[col_index] - 1 # 只有当重复次数>0时才生成重复列,否则返回NULL自动跳过 if (repeat_times > 0) { # 重复指定次数,同时给重复列重命名(比如原列V1会变成V1_rep1、V1_rep2...) replicated_cols <- replicate(repeat_times, df1[, col_index], simplify = FALSE) names(replicated_cols) <- paste0(colnames(df1)[col_index], "_rep", 1:repeat_times) replicated_cols } else { NULL } }) # 把原df1和所有重复列合并成最终数据框 final_df <- cbind(df1, do.call(cbind, unlist(repeat_columns, recursive = FALSE)))
解释:
- 先用
match对齐df2和df1的列顺序,避免因为列名顺序不一致导致重复次数对应错误; lapply遍历每一列,判断重复次数是否大于0,只处理需要重复的列;replicate生成重复列,setNames给重复列加后缀,避免列名重复;- 最后用
do.call(cbind,...)把所有重复列合并到原数据框。
方法二:Tidyverse 简洁解法(适合熟悉 tidy 语法的用户)
如果你习惯用dplyr和tidyr,这个方法逻辑更直观:
library(tidyverse) # 步骤1:把df1转成长格式,方便关联重复次数 df1_long <- df1 %>% rownames_to_column("row_id") %>% # 保留行号,方便后续合并 pivot_longer(-row_id, names_to = "name", values_to = "value") # 步骤2:结合df2的重复次数,生成需要扩展的行 expanded_data <- df1_long %>% left_join(df2, by = "name") %>% mutate(repeat_times = n - 1) %>% filter(repeat_times > 0) %>% # 跳过不需要重复的列 uncount(repeat_times, .id = "rep_num") %>% # 按次数扩展行 mutate(name = paste0(name, "_rep", rep_num)) # 给重复列重命名 # 步骤3:转回宽格式,和原df1合并 final_df <- df1 %>% rownames_to_column("row_id") %>% left_join(expanded_data %>% pivot_wider(names_from = name, values_from = value), by = "row_id") %>% select(-row_id) # 移除临时行号列
解释:
- 先把宽格式的
df1转成长格式,和df2关联得到每列的重复次数; uncount根据重复次数扩展行,同时生成重复序号;- 转回宽格式后和原数据框合并,得到最终结果。
测试验证
用你提供的示例数据测试一下:
set.seed(20) df1 <- as.data.frame(matrix(runif(n=700, min=1, max=10), nrow=10)) df2 <- data.frame("name" = colnames(df1), "n" = round(runif(n=10, min=1, max=20), 0)) # 运行任意一种方法后,查看最终列数:原10列 + sum(df2$n-1)列 ncol(final_df) # 比如如果df2$n的总和是X,那么最终列数就是10 + (X-10) = X,符合预期
注意点:
- 确保
df2$name和df1的列名完全一致,否则会出现匹配失败的情况; - 给重复列加后缀是为了避免列名重复,方便后续的数据处理和分析。
备注:内容来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

