如何在R中实现favor()函数:提取每行首个非NA值
解决方案
你需要的favor()函数可以通过dplyr::coalesce结合准引用实现,完美匹配你的需求:
library(dplyr) library(rlang) favor <- function(data, ...) { # 捕获传入的列名并展开为coalesce的参数 mutate(data, favored = coalesce(!!!ensyms(...))) }
验证示例
用你提供的测试数据验证:
data <- tibble( a = c(1, 2, 3, 4), b = c(NA, NA, 7, NA), c = c(9, NA, 11, NA) ) result <- favor(data, b, c, a) result
输出符合预期:
# A tibble: 4 × 4 a b c favored <dbl> <dbl> <dbl> <dbl> 1 1 NA 9 9 2 2 NA NA 2 3 3 7 11 7 4 4 NA NA 4
关键实现细节
- 优先级控制:
ensyms(...)会按你传入的顺序捕获列名,!!!将这些列名展开为coalesce的参数,coalesce会逐行返回第一个非缺失值,完全符合优先级要求。 - 多类型支持:只要传入的列类型可兼容(比如同类型日期、数值与字符的自动转换),函数就能正常工作。比如处理多列日期的场景:
date_data <- tibble( primary_date = as.Date(c(NA, "2023-01-02", NA, "2023-01-04")), secondary_date = as.Date(c("2023-01-01", NA, "2023-01-03", NA)), fallback_date = as.Date(c("2023-12-31", "2023-12-31", "2023-12-31", "2023-12-31")) ) favor(date_data, primary_date, secondary_date, fallback_date)
输出:
# A tibble: 4 × 4 primary_date secondary_date fallback_date favored <date> <date> <date> <date> 1 NA 2023-01-01 2023-12-31 2023-01-01 2 2023-01-02 NA 2023-12-31 2023-01-02 3 NA 2023-01-03 2023-12-31 2023-01-03 4 2023-01-04 NA 2023-12-31 2023-01-04
- R包适配:
rlang是dplyr的依赖包,在R包开发中只需声明依赖dplyr即可,无需额外引入其他包。
为什么你的最初尝试失败?
你用first(na.omit({{ ... }}))的问题在于:{{ ... }}只能处理单个参数,而...是多个列名,无法直接展开成逐行处理的逻辑。而coalesce原生支持多参数逐行取第一个非缺失值,结合准引用展开参数才是正确的思路。
内容的提问来源于stack exchange,提问作者seaweedbrain
相关产品推荐
相关产品推荐

