基于dplyr开发含ggplot绘图的自定义统计函数需求
完善你的连续变量频率统计绘图函数
我来帮你把这个函数补全,先理清楚你的需求:你想要按指定的连续变量(比如示例里的Age)分组,计算保单年数总和、出险次数,算出出险频率后用ggplot2可视化。这里核心要注意tidyverse的非标准求值处理,不然直接用参数名会报错,我会用现在tidyverse推荐的{{}}(curly-curly)语法来解决这个问题。
完整函数代码
library(dplyr) library(ggplot2) plot_stats_freq_continu <- function(df, Var, y = NAP) { # 数据处理:分组计算保单年数、出险次数和频率 data_graph <- df %>% mutate(sinistres = 1) %>% # 新增出险标记列,每一行代表1次出险记录 group_by({{Var}}) %>% # 使用{{}}引用传入的分组变量 summarise( Annee_police = sum({{y}}), # 引用传入的y变量(默认是NAP) Nb_sinistres = sum(sinistres), .groups = "drop" # 取消分组,避免后续绘图警告 ) %>% mutate(Fréquence = Nb_sinistres / Annee_police) # 计算频率,每组仅一个值无需mean # 绘图逻辑:针对连续变量的趋势展示 p <- ggplot(data_graph, aes(x = {{Var}}, y = Fréquence)) + geom_line(color = "#2c3e50", linewidth = 1) + # 折线展示整体趋势 geom_point(size = 3, color = "#e74c3c") + # 点标记每个分组的具体值 geom_smooth(method = "loess", se = TRUE, color = "#3498db", alpha = 0.2) + # 可选:添加趋势平滑线 labs( title = paste("出险频率随", rlang::as_name(enquo(Var)), "的变化趋势"), x = rlang::as_name(enquo(Var)), # 动态生成x轴标签(匹配传入的变量名) y = "出险频率(出险次数/保单年数)", caption = "数据来源:输入数据集" ) + theme_minimal() + theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold")) # 返回绘图对象 return(p) }
关键细节解释
非标准求值处理:
- 用
{{Var}}和{{y}}来引用函数参数中的变量名,这是tidyverse最新推荐的语法,比旧的enquo()+!!更简洁,能正确识别你传入的列名(比如Age)。 - 用
rlang::as_name(enquo(Var))把参数变量转换成字符串,用来动态生成图表标题和坐标轴标签,让函数更灵活通用。
- 用
数据处理优化:
- 把
df$sinistres <- rep(1,nrow(df))改成mutate(sinistres = 1),更符合dplyr的链式操作风格,避免直接修改原数据集。 - 移除了
as.data.frame(data_graph),ggplot可以直接处理dplyr生成的tibble,没必要额外转换。 - 修正了
Fréquence的计算:你原来写的mean((Nb_sinistres/Annee_police))是多余的,每组的Nb_sinistres和Annee_police都是单个汇总值,直接做除法即可。
- 把
绘图逻辑选择:
- 因为
Var是连续变量(比如年龄),用折线图+散点的组合最适合展示趋势,同时添加平滑线可以更清晰地看到整体变化方向。 - 用
theme_minimal()做基础主题,再调整标题样式,让图表更美观易读。
- 因为
示例用法
用你提供的测试数据来运行函数:
# 构造测试数据集 test_df <- tibble( Age = c(17, 18, 19), NAP = c(0.282, 0.8282, 0.223) ) # 调用函数绘图 plot_stats_freq_continu(test_df, Age)
可自定义调整的地方
- 如果想要柱状图代替折线图,把
geom_line()和geom_point()换成geom_col(fill = "#e74c3c")即可。 - 可以修改颜色、线条粗细、点的大小等视觉参数,匹配你的需求。
- 如果不需要平滑线,删掉
geom_smooth()那一行就行。
内容的提问来源于stack exchange,提问作者Naï
相关产品推荐
相关产品推荐

