求tidyverse解决方案:含非标准求值的变量更新与生成函数
用tidyverse实现自定义变量更新与生成的函数方案
需求回顾
- 当传入的日期变量
vardt早于other_dt时,将目标二元变量var的值设为NA,同时对应vardt也设为NA - 若
vardt早于baseline_dt,生成新变量{var}_incid(基于更新后的var值)和{var}_incid_dt(对应日期)
修正后的完整代码
# 加载依赖库 library(tidyverse) library(lubridate) # 生成随机日期的辅助函数 rdate <- function(x, min = paste0(format(Sys.Date(), '%Y'), '-01-01'), max = paste0(format(Sys.Date(), '%Y'), '-12-31'), sort = TRUE) { dates <- sample(seq(as.Date(min), as.Date(max), by = "day"), x, replace = TRUE) if (sort == TRUE) { sort(dates) } else { dates } } # 设置随机种子保证可复现 set.seed(42) # 生成初始数据集 das <- data.frame(id = rep(letters[1:3], each = 5), pheno = rbinom(n=15, size = 1, prob = 0.30), pheno_dt = rdate(15), baseline_dt = rdate(15), other_dt = rdate(15)) # 修正后的自定义函数 update_pheno <- function(data, var, vardt) { # 获取传入变量的字符串名称,用于生成新变量名 var_str <- rlang::as_name(rlang::enquo(var)) incid_var <- paste0(var_str, "_incid") incid_dt_var <- paste0(var_str, "_incid_dt") data %>% mutate( # 需求1:更新原变量:vardt < other_dt且var为1时设为NA {{ var }} := ifelse({{ vardt }} < other_dt & {{ var }} == 1, NA, {{ var }}), # 同步更新对应日期:原变量为NA则日期设为NA {{ vardt }} := ifelse(is.na({{ var }}), NA, {{ vardt }}), # 需求2:生成incid变量:vardt早于baseline_dt时设为NA !!incid_var := ifelse({{ vardt }} < baseline_dt & {{ var }} == 1, NA, {{ var }}), # 生成对应的incid日期变量:incid变量为NA则日期设为NA !!incid_dt_var := ifelse(is.na(!!rlang::sym(incid_var)), NA, {{ vardt }}) ) } # 调用函数(修正原代码中phenodt的笔误,应为pheno_dt) test <- update_pheno(das, pheno, pheno_dt)
关键修正点说明
- 非标准求值处理:使用tidyverse推荐的
{{ }}(curly-curly操作符)替代eval(substitute()),直接在mutate中引用传入的非标准参数,代码更简洁易读。 - 动态变量名赋值:通过
rlang::enquo()捕获参数并转成字符串,结合!!(bang-bang操作符)和:=实现动态变量名的赋值,解决原函数中直接用paste0()作为变量名的错误写法。 - 逻辑修正:补全原函数中缺失的条件关联,确保变量和日期的更新逻辑一致,同时正确关联新生成变量的依赖关系。
内容的提问来源于stack exchange,提问作者ceruleanclouds
相关产品推荐
相关产品推荐

