R语言多列提取首个非NA值:优雅实现DataFrame转换
高效批量处理ID/No列对的R语言方案
针对你需要批量处理成对X_ID/X_No列的需求,这里提供两种无需显式循环的优雅方案,完全适配上千组列的场景:
方案一:Base R原生实现
无需额外安装包,利用向量化操作完成:
# 提取所有列组的前缀(A、B、C...) groups <- unique(sub("_.*", "", colnames(df))) # 定义处理单个列组的函数 extract_pair <- function(group) { id_col <- paste0(group, "_ID") no_col <- paste0(group, "_No") no_values <- df[[no_col]] # 找到第一个非NA值的位置(首行非NA则直接取第1行) target_row <- which(!is.na(no_values))[1] data.frame(ID = df[[id_col]][target_row], No = no_values[target_row]) } # 批量处理所有组并合并结果 df2 <- do.call(rbind, sapply(groups, extract_pair, simplify = FALSE))
方案二:Tidyverse管道式实现
利用tidyverse的宽转长功能,代码更直观易读:
library(tidyverse) df2 <- df %>% # 添加行号用于定位 mutate(row_num = row_number()) %>% # 将成对列转成长表,自动按前缀分组 pivot_longer( cols = -row_num, names_to = c("group", ".value"), names_pattern = "(.*)_(ID|No)" ) %>% # 每个组筛选出第一个非NA No对应的行 group_by(group) %>% filter(row_num == min(row_num[!is.na(No)])) %>% ungroup() %>% # 保留需要的列并恢复原列组顺序 select(ID, No) %>% arrange(match(group, groups))
两种方案最终都会生成和示例一致的df2,且均为批量处理逻辑,不会因列组数量增加导致性能瓶颈。
内容的提问来源于stack exchange,提问作者bilmawr
相关产品推荐
相关产品推荐

