如何在R语言中用dplyr按行合并因子生成flavor列
问题:将多列非NA值合并为分类列(dplyr通用方案)
原始数据
df <- data.frame(id = c("001", "002", "003", "004"), banana = c("banana", NA, NA, NA), apple = c(NA, "apple", "apple", NA), orange = c("orange", NA, NA, NA), mango = c(NA, NA, NA, "mango"))
输出:
id banana apple orange mango 001 banana NA orange NA 002 NA apple NA NA 003 NA apple NA NA 004 NA NA NA mango
需求
将banana、apple、orange、mango列合并为名为flavor的新列:
- 若一行有多个非NA值,标记为
mixed - 若一行只有一个非NA值,取该值作为
flavor内容 - 方案需兼容数据框中存在其他列的情况
解决方案
方法1:rowwise + c_across(直观易读)
适合中小规模数据,代码逻辑清晰:
library(dplyr) df_processed <- df %>% rowwise() %>% mutate( # 提取当前行目标列的非NA值 non_na_vals = list(na.omit(c_across(banana:mango))), # 根据非NA值数量生成flavor flavor = case_when( length(non_na_vals) > 1 ~ "mixed", length(non_na_vals) == 1 ~ non_na_vals[[1]], TRUE ~ NA_character_ # 处理全NA的情况 ) ) %>% ungroup() %>% select(-non_na_vals) # 删除临时中间列
方法2:purrr::pmap(高效无rowwise)
适合大规模数据,避免rowwise的性能损耗:
library(dplyr) library(purrr) df_processed <- df %>% mutate( flavor = pmap_chr(select(., banana:mango), function(...) { non_na <- na.omit(c(...)) case_when( length(non_na) > 1 ~ "mixed", length(non_na) == 1 ~ non_na, TRUE ~ NA_character_ ) }) )
处理结果
df_processed #> id banana apple orange mango flavor #> 1 001 banana NA orange NA mixed #> 2 002 NA apple NA NA apple #> 3 003 NA apple NA NA apple #> 4 004 NA NA NA mango mango
通用性说明
- 若目标列不连续,可将
c_across(banana:mango)替换为c_across(c(banana, apple, orange, mango)),按需指定列名 - 两种方法都会保留数据框中的其他列,无需额外处理
- 自动处理全NA的行,返回
NA_character_
内容的提问来源于stack exchange,提问作者aerw4
相关产品推荐
相关产品推荐

