合并名称相似的DataFrame列
更简便的列合并方案(针对规律命名的DataFrame列)
当然有更简便的方案!你这种列名带固定规律(gN_paramM)的宽表转长表需求,用tidyverse工具链里的pivot_longer() + pivot_wider()组合就能轻松搞定,比手动写grepl逻辑简洁太多了。
步骤演示
首先先还原你的示例数据:
library(tidyverse) # 构造示例DataFrame df <- tibble( g1_param1 = c(NA, 1), g2_param1 = c(7, NA), g1_param2 = c(NA, 1), g2_param2 = c(4, NA) )
接下来用两行核心代码完成合并:
df_merged <- df %>% # 第一步:把所有列转成长格式,提取出param部分作为新列 pivot_longer( cols = everything(), # 选中所有列 names_pattern = "g\\d+_(param\\d+)", # 正则匹配:捕获paramM部分 names_to = "param", # 捕获到的内容作为新列"param" values_to = "value", # 原列的值存入"value"列 values_drop_na = TRUE # 自动丢弃NA值 ) %>% # 第二步:把长格式转回宽格式,param作为列名 pivot_wider(names_from = param, values_from = value)
运行后得到的结果就是你想要的:
# A tibble: 2 × 2 param1 param2 <dbl> <dbl> 1 7 4 2 1 1
代码解释
names_pattern = "g\\d+_(param\\d+)":用正则表达式匹配列名,g\\d+匹配开头的g1/g2前缀,(param\\d+)是捕获组,专门提取出param1/param2这类核心变量名。values_drop_na = TRUE:因为你的数据里每行同一param只有一个非NA值,这一步自动过滤掉无效的NA,避免后续转宽时出现重复行。- 最后用
pivot_wider把提取出的param名转回列,完美实现合并。
备选:Base R方法(无需tidyverse)
如果你不想加载tidyverse包,也可以用Base R的分组+遍历实现:
# 按列名的param部分分组 col_groups <- split.default(df, sub("g\\d+_", "", names(df))) # 每组内逐行取非NA值 df_merged_base <- data.frame(lapply(col_groups, function(cols) { apply(cols, 1, function(row) row[!is.na(row)]) }))
不过这个方法在处理大型数据集时效率不如tidyverse,代码可读性也稍弱,更推荐前者。
内容的提问来源于stack exchange,提问作者FloLe
相关产品推荐
相关产品推荐

