在mutate+across中调用自定义函数计算svymean返回NA的问题排查
问题原因与修复方案
核心错误点
- across参数类型不匹配:
你在across的匿名函数里用\(x),这里的x是列的数值向量(比如Var1的c(1,1,NA,NA,1,0)),但自定义函数的VAR参数需要的是变量名字符串。函数里的eval(parse(text = VAR))无法解析数值向量,导致判断条件不满足,直接进入else分支返回NA。 - pick函数用法错误:
pick(x,X_PSU,X_STSTR,WT)中的x是数值向量,而pick需要传入列名,这会生成结构错误的数据框,进一步导致后续的svydesign创建失败。
修复步骤
第一步:优化自定义函数(替换不安全的eval(parse))
用tidyverse规范的方式替代eval(parse),避免解析错误:
calc_wt_mean_var_fn_df_ex = function(data, VAR){ var_vals = data[[VAR]] # 判断非NA唯一值数量是否≥2 if(length(unique(na.omit(var_vals))) > 1){ # 创建调查设计对象 svydes = svydesign(id =~X_PSU, strata =~ X_STSTR, weights =~WT, data = data %>% filter(!is.na(WT) & !is.na(X_PSU)), nest = TRUE ) # 用rlang::sym转换变量名为公式,避免字符串拼接 res = svymean(~!!rlang::sym(VAR), svydes, na.rm = TRUE) %>% as_tibble() ans = res$mean } else{ ans = NA } return(ans) }
第二步:修正across的调用逻辑
用.col获取当前列的名字(字符串类型),并传递完整数据框给函数(因为函数需要用到X_PSU、X_STSTR、WT等辅助列):
output.ds.2018 = input.ds.2018 %>% mutate(across(all_of(regularVar_names_ex), ~ calc_wt_mean_var_fn_df_ex(cur_data(), VAR = .col), .names = "wt_mean_{.col}"))
验证结果
运行修正后的代码后,会生成符合预期的列:
wt_mean_Var1列:所有行值为0.505(对应加权均值5.1/10.1≈0.50495)wt_mean_Var2列:所有行值为0.457(对应加权均值10.1/22.1≈0.457)
内容的提问来源于stack exchange,提问作者abrar
相关产品推荐
相关产品推荐

