如何按列名共性分组合并列并去除NA值(R语言)
解决方案
可以通过两种方式实现需求,分别基于tidyverse工具包和基础R语法:
方法一:使用tidyverse工具包
library(tidyverse) # 示例数据 data <- data.frame( X2020_1 = c("A", NA, "B"), X2020_2 = c("A", "C", NA), X2021_1 = c("A", NA, "C"), X2021_2 = c(NA, NA, "A") ) result <- data %>% mutate(row_id = row_number()) %>% pivot_longer(-row_id, names_to = "year_col", values_to = "value") %>% mutate(year = str_extract(year_col, "^X\\d{4}")) %>% group_by(row_id, year) %>% summarise(combined = list(na.omit(value)), .groups = "drop") %>% mutate(combined = ifelse(lengths(combined) == 0, NA, combined)) %>% pivot_wider(names_from = year, values_from = combined) %>% select(-row_id) print(result)
步骤说明:
- 添加行号标记每一行的原始位置
- 将宽格式数据转为长格式,便于按年份分组处理
- 从列名中提取年份前缀(如
X2020)作为分组依据 - 按行号和年份分组,过滤NA值后将剩余值转为列表
- 把空列表(对应分组内全为NA的情况)替换为NA
- 转回宽格式并移除行号,得到最终结果
方法二:使用基础R语法
# 示例数据 data <- data.frame( X2020_1 = c("A", NA, "B"), X2020_2 = c("A", "C", NA), X2021_1 = c("A", NA, "C"), X2021_2 = c(NA, NA, "A") ) # 按年份分组列名 year_groups <- list( X2020 = grep("X2020", colnames(data), value = TRUE), X2021 = grep("X2021", colnames(data), value = TRUE) ) # 定义行处理函数:过滤NA,全NA则返回NA process_row <- function(row_cols) { vals <- na.omit(row_cols) if (length(vals) == 0) NA else vals } # 对每个年份组逐行处理 result <- data.frame( X2020 = apply(data[, year_groups$X2020], 1, process_row), X2021 = apply(data[, year_groups$X2021], 1, process_row) ) print(result)
步骤说明:
- 通过正则匹配将列名按年份分组
- 定义处理函数,对每行的指定列过滤NA,全NA时返回NA
- 使用
apply按行处理每个年份组的列,将结果组合为新数据框
两种方法最终都会得到期望的结果:
X2020 X2021 1 c("A", "A") A 2 C <NA> 3 B c("C", "A")
内容的提问来源于stack exchange,提问作者ifoxfoot
相关产品推荐
相关产品推荐

