如何在ggplot2的fct_reorder()中使用NSE复用不同数据框绘图
在ggplot2的fct_reorder()中使用非标准求值(NSE)批量生成图表
我来帮你搞定这个问题!要在fct_reorder()里用NSE实现重复绘图,核心是用tidyverse的curly curly运算符({{ }}),它能帮你把传入的参数动态映射到数据框的列上,完美适配批量场景。
第一步:整理示例数据
先把你提供的示例数据转换成可直接复用的格式:
library(tibble) travel_data <- tribble( ~travel_time_br30, ~travel_time_br30_int, ~time_reduction, ~shift, ~not_shift, ~total, "0-30", 0, 10, 2780, 3268, 6048, "0-30", 0, 20, 2779, 3269, 6048, "0-30", 0, 30, 2984, 3064, 6048, "0-30", 0, 40, 3211, 2837, 6048, "30-60", 30, 10, 2139, 2007, 4146, "30-60", 30, 20, 2159, 1987, 4146, "30-60", 30, 30, 2363, 1783, 4146, "30-60", 30, 40, 2478, 1668, 4146 # 补全缺失的not_shift值 )
第二步:用NSE写可复用的绘图函数
我们定义一个函数,接受数据框和要用来排序的列作为参数,用{{ }}在fct_reorder()和绘图映射中引用参数:
library(ggplot2) library(forcats) library(dplyr) library(stringr) plot_travel <- function(data, sort_col) { data %>% ggplot(aes( # 用{{ }}动态传入排序列,让fct_reorder识别数据框中的列 x = fct_reorder(travel_time_br30, {{ sort_col }}), y = {{ sort_col }} )) + geom_col(fill = "#2E86AB") + labs( x = "Travel Time Range", # 自动生成轴标签和标题,不用手动修改 y = str_to_title(rlang::as_label(enquo(sort_col))), title = str_glue("Travel Time vs {str_to_title(rlang::as_label(enquo(sort_col)))}") ) + theme_minimal() }
第三步:批量生成图表
现在你只需要传入不同的列名,就能快速生成对应图表:
# 生成针对shift列的图表 plot_shift <- plot_travel(travel_data, shift) # 生成针对not_shift列的图表 plot_not_shift <- plot_travel(travel_data, not_shift) # 生成针对total列的图表 plot_total <- plot_travel(travel_data, total) # 查看其中一个图表(比如shift的) print(plot_shift)
扩展:支持降序排序
如果需要按降序排序,只需要给函数加一个参数,在fct_reorder()中传入.desc参数:
plot_travel <- function(data, sort_col, desc = FALSE) { data %>% ggplot(aes( x = fct_reorder(travel_time_br30, {{ sort_col }}, .desc = desc), y = {{ sort_col }} )) + geom_col(fill = "#2E86AB") + labs( x = "Travel Time Range", y = str_to_title(rlang::as_label(enquo(sort_col))), title = str_glue("Travel Time vs {str_to_title(rlang::as_label(enquo(sort_col)))} ({ifelse(desc, 'Descending', 'Ascending')})") ) + theme_minimal() } # 降序排序的示例 plot_shift_desc <- plot_travel(travel_data, shift, desc = TRUE)
原理说明
{{ sort_col }}是tidyverse NSE的核心语法,它会把你传入的参数(比如shift)“解引用”成数据框中的实际列,让fct_reorder()和ggplot能正确识别。而rlang::as_label(enquo(sort_col))则是把传入的参数转换成字符串,用来动态生成标题和轴标签,让函数更灵活。
内容的提问来源于stack exchange,提问作者HSJ
相关产品推荐
相关产品推荐

