如何在R中将dataframe重名列合并堆叠为对应单列?
R实现重名列自动堆叠合并
需求说明
创建data.frame时如果传入重复列名,R会自动为后续重复列添加.1/.2这类数字后缀,需要将同源重名列的内容堆叠合并为单列,且代码可适配任意列顺序的场景。
测试用示例数据
# 创建测试用含重名列的data.frame emp.data <- data.frame( emp_name = c("Rick","Dan","Michelle","Ryan","Gary"), salary = c(623.3,515.2,611.0,729.0,843.25), salary = c(700.3,600.2,721.0,730.5,845.4), emp_name = c("Kevin","Tracy","Thompson","Peter","Bevan"), stringsAsFactors = FALSE )
原始输出的列名会自动变为emp_name salary salary.1 emp_name.1。
实现方案
无依赖的Base R实现(推荐,兼容性最好)
代码逻辑:先提取所有列名的根(去除后缀的原始列名),再按根分组堆叠所有同源列的内容,自动保留列首次出现的顺序,适配任意列排列场景。
# 提取所有列名的根(去掉末尾.加数字的自动后缀) col_root <- sub("\\.\\d+$", "", names(emp.data)) # 保留列首次出现的顺序作为结果列顺序 unique_cols <- unique(col_root) # 遍历每个根列名,堆叠对应所有列的内容 result <- data.frame( lapply(unique_cols, function(col) { unlist(emp.data[, col_root == col, drop = FALSE], use.names = FALSE) }), row.names = NULL, check.names = FALSE ) # 给结果设置列名 names(result) <- unique_cols
Tidyverse简洁实现
如果你的项目已经使用tidyverse生态,可以用更简洁的写法:
library(tidyverse) result <- emp.data %>% # 还原列名为去掉后缀的原始重名状态 rename_with(~str_remove(., "\\.\\d+$")) %>% # 按列名分组堆叠,.value参数自动按同源列合并 pivot_longer( cols = everything(), names_to = ".value", names_pattern = "(.*)" )
输出结果验证
打印result即可得到预期输出:
emp_name salary 1 Rick 623.30 2 Dan 515.20 3 Michelle 611.00 4 Ryan 729.00 5 Gary 843.25 6 Kevin 700.30 7 Tracy 600.20 8 Thompson 721.00 9 Peter 730.50 10 Bevan 845.40
内容的提问来源于stack exchange,提问作者Kevin Tracey
相关产品推荐
相关产品推荐

