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

如何在ggplot2渐变图例中添加平均线?

在ggplot2渐变图例色条中添加平均线

你之前用annotate的问题在于,这个函数是在主绘图区添加元素,而非图例内部,所以会破坏原有布局。下面是两种可行的实现方案:


方案1:自定义图例向导(推荐)

通过重写guide_colorbar的绘制逻辑,直接在色条上添加平均线,代码可复用性高:

1. 计算目标均值

mean_np <- mean(parties_ger_plz$np, na.rm = TRUE)

2. 自定义带平均线的颜色条向导

guide_colorbar_with_mean <- function(mean_val, ...) {
  guide <- guide_colorbar(...)
  # 重写图例绘制函数
  guide$draw <- function(self, theme, x, y, width, height, ...) {
    # 先绘制默认的颜色条
    base_bar <- NextMethod()
    # 将均值归一化到色条的0-1高度范围
    val_limits <- self$scale$get_limits()
    y_normalized <- (mean_val - val_limits[1]) / (val_limits[2] - val_limits[1])
    # 创建平均线元素
    mean_line <- grid::segmentsGrob(
      x0 = x, x1 = x + width,
      y0 = y + height * y_normalized, y1 = y + height * y_normalized,
      gp = grid::gpar(col = "blue", lwd = 1.5, lty = "dashed")
    )
    # 合并颜色条与平均线
    grid::grobTree(base_bar, mean_line)
  }
  guide
}

3. 应用到你的绘图中

修改scale_fill_gradientn的guide参数,替换为自定义向导:

main_map <- ggplot() +
  geom_sf(data = parties_ger_plz, aes(fill = np), color = "white", linewidth = 0.045) +
  scale_fill_gradientn(
    name = "Klagequote (%)",
    na.value = "#9DBF9E",
    labels = scales::label_number(scale = 1, suffix = " %", accuracy = 1),
    colors = c("#9DBF9E", "#FCB97D", "#A84268"),
    # 使用自定义图例
    guide = guide_colorbar_with_mean(
      mean_val = mean_np,
      frame.colour = "black",
      frame.linewidth = 0.3,
      ticks = TRUE,
      ticks.colour = "black",
      barwidth = 0.5,
      barheight = 10,
      title.position = "top"
    )
  ) +
  geom_sf(data = geo_data_ger_adm_states, linewidth = 0.25, color = "black", fill = "transparent") +
  coord_sf(expand = FALSE) +
  theme_minimal() +
  theme(
    legend.text = element_text(size = 6),
    legend.title = element_text(size = 7),
    legend.key.size = unit(0.3, "cm")
  )

之后继续按照你原有的代码逻辑构建big_map、noth_west_germany和final_map即可,此时图例色条上会显示蓝色虚线的平均线。


方案2:修改已生成的图例gtable

如果你不想自定义向导,可以先绘制好图,再提取图例并手动添加线段:

1. 先绘制基础地图(用默认图例)

main_map <- ggplot() +
  geom_sf(data = parties_ger_plz, aes(fill = np), color = "white", linewidth = 0.045) +
  scale_fill_gradientn(
    name = "Klagequote (%)",
    na.value = "#9DBF9E",
    labels = scales::label_number(scale = 1, suffix = " %", accuracy = 1),
    colors = c("#9DBF9E", "#FCB97D", "#A84268"),
    guide = guide_colorbar(
      frame.colour = "black",
      frame.linewidth = 0.3,
      ticks = TRUE,
      ticks.colour = "black",
      barwidth = 0.5,
      barheight = 10,
      title.position = "top"
    )
  ) +
  geom_sf(data = geo_data_ger_adm_states, linewidth = 0.25, color = "black", fill = "transparent") +
  coord_sf(expand = FALSE) +
  theme_minimal() +
  theme(
    legend.text = element_text(size = 6),
    legend.title = element_text(size = 7),
    legend.key.size = unit(0.3, "cm")
  )

2. 提取并修改图例

library(gtable)
library(grid)

# 将ggplot对象转为gtable
gt <- ggplotGrob(main_map)
# 定位图例所在的grob
legend_pos <- which(grepl("guide-box", gt$layout$name))
legend_grob <- gt$grobs[[legend_pos]]

# 找到色条元素
bar_pos <- which(sapply(legend_grob$grobs, function(x) x$name == "bar"))
color_bar <- legend_grob$grobs[[bar_pos]]

# 计算均值对应的色条位置
val_range <- range(parties_ger_plz$np, na.rm = TRUE)
y_norm <- (mean_np - val_range[1]) / (val_range[2] - val_range[1])
line_y <- color_bar$y + color_bar$height * y_norm

# 添加平均线
mean_line <- segmentsGrob(
  x0 = color_bar$x, x1 = color_bar$x + color_bar$width,
  y0 = line_y, y1 = line_y,
  gp = gpar(col = "blue", lwd = 1.5, lty = "dashed")
)

# 合并色条与平均线
legend_grob$grobs[[bar_pos]] <- grobTree(color_bar, mean_line)
gt$grobs[[legend_pos]] <- legend_grob

3. 绘制或组合修改后的图

# 直接绘制修改后的图
grid.draw(gt)

# 或者继续组合到你的final_map中
final_map <- ggdraw(gt) +
  draw_plot(big_map, x = 0.635, y = 0.05, width = 0.4, height = 0.4) +
  coord_fixed() +
  theme_minimal() +
  theme(
    plot.background = element_blank(),
    plot.margin = unit(c(0, 0, 0, 0), "cm")
  )

内容的提问来源于stack exchange,提问作者Niklas H.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:24:55