在R中用函数创建分组频率表数据框时遇错求助
分组统计频率表函数的错误修正
手动实现的正确代码
先看手动生成use和ehr列频率表的正确代码:
use_df <- w1w2 %>% group_by(wave, use) %>% summarise(cnt_use = n()) %>% drop_na(use) %>% mutate(perc_use = case_when( wave == "W1" ~ cnt_use / sum(cnt_use), wave == "W2" ~ cnt_use / sum(cnt_use))) ehr_df <- w1w2 %>% group_by(wave, ehr) %>% summarise(cnt_ehr = n()) %>% drop_na(ehr) %>% mutate(perc_ehr = case_when( wave == "W1" ~ cnt_ehr / sum(cnt_ehr), wave == "W2" ~ cnt_ehr / sum(cnt_ehr)))
原函数的错误点
你编写的函数存在以下问题:
- 参数引用不匹配:
enquo(varname)中的varname与函数定义的参数var_name不一致,应为enquo(var_name) - 起始操作无效:
df_!!varname是错误写法,需从传入的df对象开始链式操作 - 动态列名语法错误:
cnt_!!var_name不符合tidyeval规则,动态列名赋值需结合:=与字符串拼接/glue语法 - 无返回值且视图调用错误:函数未返回处理后的数据集,
view(df_!!varname)的写法也不合法 - 逻辑冗余:
case_when中两个分支逻辑完全一致,可直接简化为cnt / sum(cnt)
修正后的函数
使用{{ }}(curly-curly)语法简化动态变量引用,同时修正所有错误:
library(dplyr) library(glue) summary_fn <- function(var_name, df) { # 生成动态列名 cnt_col <- glue("cnt_{{var_name}}") perc_col <- glue("perc_{{var_name}}") result <- df %>% group_by(wave, {{var_name}}) %>% summarise(!!cnt_col := n(), .groups = "drop_last") %>% drop_na({{var_name}}) %>% mutate(!!perc_col := !!sym(cnt_col) / sum(!!sym(cnt_col))) View(result) return(result) } # 调用示例 use_result <- summary_fn(use, w1w2) ehr_result <- summary_fn(ehr, w1w2)
也可以用更简洁的字符串拼接方式实现:
summary_fn <- function(var_name, df) { var_str <- deparse(substitute(var_name)) cnt_col <- paste0("cnt_", var_str) perc_col <- paste0("perc_", var_str) df %>% group_by(wave, {{var_name}}) %>% summarise(!!cnt_col := n(), .groups = "drop_last") %>% drop_na({{var_name}}) %>% mutate(!!perc_col := !!sym(cnt_col) / sum(!!sym(cnt_col))) %>% View() }
补充说明
.groups = "drop_last"用于在summarise后仅保留wave分组,确保求和是按每个wave单独计算的deparse(substitute(var_name))用于将传入的变量名转为字符串,方便生成动态列名- 修正后的函数会返回处理后的数据集,便于后续分析使用
内容的提问来源于stack exchange,提问作者Alex Braga
相关产品推荐
相关产品推荐

