如何用purrr包的map函数批量生成多变量同类型可视化图?
问题分析与解决方案
你的代码存在的错误
- 函数参数与内部变量不匹配:
p1func的参数定义为df,但函数内部直接使用了purrr专属的占位符.x,该变量未在函数中定义,导致逻辑断裂。 map_at使用逻辑错误:map_at(df, c(2:4), ~p1func)是对数据集的第2-4列单独处理,此时传入p1func的是单个列向量,而非完整数据集,函数中需要的age_f列不存在于单个向量中,无法完成分组计算。- 函数调用未传参:
~p1func没有将当前处理的列传递给函数,即使逻辑正确,也会因缺少必要参数报错。
正确实现方式
我们可以通过传递变量名给自定义函数,结合purrr::map批量生成图表,同时利用tidyeval语法处理变量引用。
方法1:字符串变量名 + tidyeval
# 定义通用绘图函数,接收数据集和目标变量名(字符串) plot_rating <- function(df, var_name) { df %>% filter(!is.na(.data[[var_name]])) %>% # 用.data[[var_name]]引用字符串变量 group_by(age_f, .data[[var_name]]) %>% summarize(Count = n(), .groups = "drop") %>% # 显式设置.groups避免分组警告 mutate(pct = round(prop.table(Count)*100, 0), res = str_c(pct, "%")) %>% ggplot(aes(x = age_f, y = pct, fill = .data[[var_name]])) + geom_col(width = 0.6) + theme_bw() + theme( axis.title.x = element_blank(), axis.text.y = element_text(size = 25, face = "bold"), axis.title.y = element_blank(), legend.text = element_text(size = 25), legend.title = element_blank(), axis.line.y.left = element_line(color = 'gray'), panel.border = element_blank() ) + geom_text(aes(label = res), position = position_stack(vjust = .5), size = 10) + coord_flip() + scale_fill_brewer() + labs(title = str_c("Rating: ", var_name)) # 可选:添加标题区分不同图表 } # 指定需要绘图的变量列表 vars_to_plot <- c("awareness_rating", "risk_rating", "like_rating") # 批量生成图表,返回ggplot对象列表 plot_list <- map(vars_to_plot, ~plot_rating(df, .x)) # 查看单个图表,例如第二个 plot_list[[2]] # 若需一次性展示所有图表,可使用patchwork包 # library(patchwork) # wrap_plots(plot_list, ncol = 1)
方法2:转换为长格式数据(更贴合tidyverse思维)
先将宽格式数据集转为长格式,再按变量分组绘图:
# 转换为长格式 df_long <- df %>% pivot_longer( cols = c(awareness_rating, risk_rating, like_rating), names_to = "rating_type", values_to = "rating_value" ) %>% filter(!is.na(rating_value)) # 按rating_type分组批量生成图表 plot_list <- df_long %>% group_split(rating_type) %>% map(function(sub_df) { sub_df %>% group_by(age_f, rating_value) %>% summarize(Count = n(), .groups = "drop") %>% mutate(pct = round(prop.table(Count)*100, 0), res = str_c(pct, "%")) %>% ggplot(aes(x = age_f, y = pct, fill = rating_value)) + geom_col(width = 0.6) + theme_bw() + theme( axis.title.x = element_blank(), axis.text.y = element_text(size = 25, face = "bold"), axis.title.y = element_blank(), legend.text = element_text(size = 25), legend.title = element_blank(), axis.line.y.left = element_line(color = 'gray'), panel.border = element_blank() ) + geom_text(aes(label = res), position = position_stack(vjust = .5), size = 10) + coord_flip() + scale_fill_brewer() + labs(title = unique(sub_df$rating_type)) }) # 查看第三个图表 plot_list[[3]]
补充:批量保存图表
若需要将生成的图表批量保存到本地,可使用purrr::walk2配合ggsave:
walk2(plot_list, vars_to_plot, ~ggsave( filename = str_c(.y, ".png"), plot = .x, width = 10, height = 8 ))
内容的提问来源于stack exchange,提问作者ffew
相关产品推荐
相关产品推荐

