You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将ggplot2高亮条形图最大值的两个函数合并为单个函数?

问题

我正在为流行病学团队开发内部R包,目标是简化仅填充最大值条形的条形图制作流程。目前已经实现了两个可用函数,但希望进一步精简为单个函数,却不清楚如何传递ggplot()的数据与映射参数。我了解gghighlight包,但希望自行实现,期望的调用方式如下:

ggplot(data = df, aes(x = locations, y = scores, fill = scores)) +
  geom_col() +
  theme_classic() +
  highlight_max_value(pal = "London Pink", highlight = scores)

现有代码如下:

library(ggplot2)

highlight_max <- function(col){
  if(!inherits(col, c("numeric","integer"))){
    stop("Input data not a number/integer.")
  }
  out = rank(-col) %in% 1
  return(out)
}

scale_fill_highlight <- function(pal = NULL){
  highlight_combos = list(
    `London Pink` = c("FALSE"="#cccccc","TRUE"="#9E0059"),
    Mustard = c("FALSE"="#cccccc","TRUE"="#DCA000"),
    Blue = c("FALSE"="#cccccc","TRUE"="#00577D")
  )
  discrete_scale("fill", "cd", palette = colorRampPalette(highlight_combos[[pal]]))
}

df <- data.frame(
  locations = letters[1:5],
  scores = c(89,62,74,88,89.5)
  )

ggplot(data = df, aes(x = locations, y = scores, fill = highlight_max(scores), label = scores)) +
  geom_col() +
  theme_classic() +
  scale_fill_highlight(pal = "London Pink") +
  scale_y_continuous(expand = c(0,0), limits = c(0,100))
解决方案

要实现单个highlight_max_value函数,需将最大值判断逻辑与自定义填充刻度整合,同时兼容ggplot的语法规则。核心步骤如下:

  1. 解析传入的映射变量,实现非标准求值
  2. 内部完成“是否为最大值”的判断,替换原fill映射
  3. 整合配色逻辑,生成自定义填充刻度

实现代码

library(ggplot2)
library(rlang)

highlight_max_value <- function(pal = "London Pink", highlight){
  # 定义预设配色组合
  highlight_combos <- list(
    `London Pink` = c("FALSE"="#cccccc","TRUE"="#9E0059"),
    Mustard = c("FALSE"="#cccccc","TRUE"="#DCA000"),
    Blue = c("FALSE"="#cccccc","TRUE"="#00577D")
  )
  
  # 校验配色有效性
  if(!pal %in% names(highlight_combos)){
    stop(sprintf("配色'%s'不存在,可选值:%s", pal, paste(names(highlight_combos), collapse = ", ")))
  }
  
  # 解析传入的高亮变量
  highlight_var <- enquo(highlight)
  
  # 返回ggplot元素列表:包含映射替换和刻度设置
  list(
    aes(fill = !!highlight_var == max(!!highlight_var, na.rm = TRUE)),
    discrete_scale(
      "fill", 
      "highlight_max", 
      palette = function(n) highlight_combos[[pal]],
      labels = c("非最大值", "最大值"),
      guide = guide_legend(title = NULL)
    )
  )
}

# 测试数据
df <- data.frame(
  locations = letters[1:5],
  scores = c(89,62,74,88,89.5)
)

# 调用示例(匹配期望语法)
ggplot(data = df, aes(x = locations, y = scores)) +
  geom_col() +
  theme_classic() +
  highlight_max_value(pal = "London Pink", highlight = scores) +
  scale_y_continuous(expand = c(0,0), limits = c(0,100))

关键细节

  • 用rlang::enquo()处理传入的highlight参数,支持ggplot的映射语法
  • 函数返回列表,可直接添加到ggplot对象链中,无需拆分调用
  • 保留原有的最大值判断逻辑(max()自动识别唯一最大值,若有多个相同最大值会全部高亮)
  • 增加配色校验和图例优化,提升函数鲁棒性和可视化体验

内容的提问来源于stack exchange,提问作者SeniorAthlete

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 12:50:16