为每个站点的图例添加虚线平均

问题描述 投票:0回答:1

我有一个 ggplot,可以为 5 个站点中的每一个绘制 3 个数据点。我根据站点对线条和点进行了颜色编码。然后,我绘制每个站点的平均值并进行颜色匹配,但将线设为虚线。我想为每个站点的图例添加一条虚线,并在图例的每条实线下添加相应的颜色。

数据

chl_no_est <- structure(list(sample_date = structure(c(1683763200, 1683763200, 
1683676800, 1683676800, 1683676800, 1689206400, 1689206400, 1689120000, 
1689120000, 1689120000, 1694649600, 1694649600, 1694563200, 1694649600, 
1694563200), tzone = "America/Los_Angeles", class = c("POSIXct", 
"POSIXt")), event = c("May 2023", "May 2023", "May 2023", "May 2023", 
"May 2023", "July 2023", "July 2023", "July 2023", "July 2023", 
"July 2023", "September 2023", "September 2023", "September 2023", 
"September 2023", "September 2023"), station_name = c("TMDL-R1", 
"TMDL-R2", "TMDL-CL", "TMDL-R3", "TMDL-R4", "TMDL-R1", "TMDL-R2", 
"TMDL-CL", "TMDL-R3", "TMDL-R4", "TMDL-R1", "TMDL-R2", "TMDL-CL", 
"TMDL-R3", "TMDL-R4"), var = c("Chlorophyll a", "Chlorophyll a", 
"Chlorophyll a", "Chlorophyll a", "Chlorophyll a", "Chlorophyll a", 
"Chlorophyll a", "Chlorophyll a", "Chlorophyll a", "Chlorophyll a", 
"Chlorophyll a", "Chlorophyll a", "Chlorophyll a", "Chlorophyll a", 
"Chlorophyll a"), result = c(8.86, 41.3, 8.01, 10.5, 112, 53.2, 
81.7, 61.9, 74.5, 103, 108, 53.3, 10.6, 27.8, 24.4), mean_var = c(56.6866666666667, 
58.7666666666667, 26.8366666666667, 37.6, 79.8, 56.6866666666667, 
58.7666666666667, 26.8366666666667, 37.6, 79.8, 56.6866666666667, 
58.7666666666667, 26.8366666666667, 37.6, 79.8)), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -15L), groups = structure(list(
    station_name = c("TMDL-CL", "TMDL-R1", "TMDL-R2", "TMDL-R3", 
    "TMDL-R4"), .rows = structure(list(c(3L, 8L, 13L), c(1L, 
    6L, 11L), c(2L, 7L, 12L), c(4L, 9L, 14L), c(5L, 10L, 15L)), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -5L), .drop = TRUE))



dry_season_1year_events <- data.frame(event = c("May 2023", "June 2023", "July 2023", "August 2023", "September 2023"))


代码

annotation_mean_chl <- chl_no_est %>% 
  select(event, station_name, result) %>% 
  group_by(station_name) %>% 
  mutate(avg_result = mean(result))
  


chl_no_est$event <- factor(chl_no_est$event, levels = dry_season_1year_events$event)


annotation_chl <- data.frame(
   x = c("May 2023"),
   y = c(158),
   label = c("Target Seasonal Average: 150 mg/m2")
)



ggplot() +
  geom_line(data = chl_no_est, aes(x = event, y = result, color = station_name, group = station_name), size = 0.8) +
  geom_point(data = chl_no_est, aes(x = event, y = result, color = station_name, group = station_name)) +
  theme_classic() +
  geom_hline(yintercept = c(150), linetype = "solid", color = "black", size = 0.7) +
  geom_line(data = annotation_mean_chl, aes(x=event, y=avg_result, color = station_name, group = station_name), linetype=2) +
  scale_color_viridis(discrete = TRUE, name = NULL) +
  theme(plot.title = element_text(hjust = 0.5),
        axis.title.x = element_blank(),
        legend.position = "bottom",  # Place legend under the x-axis
        legend.box = "horizontal",
        panel.grid.major.y = element_line(size=.01, color="grey60" )) +
  labs(y="Chlorophyll a (mg/m2)") +
  scale_y_continuous(limits = c(0, 200), breaks = seq(0, 200, by = 20),
                     expand = c(0,0)) +
  geom_text(data = annotation_chl, aes(x=x, y=y, label=label), nudge_x = 0.1)

Needs Dashed Lines on Legend

没有,不确定如何继续。

r ggplot2
1个回答
0
投票

一个快速简单的选择是使用

ggnewscale
包为虚线平均线添加第二个色标。

library(ggplot2)
library(viridis)

ggplot() +
  geom_line(data = chl_no_est, aes(x = event, y = result, color = station_name, group = station_name), size = 0.8) +
  geom_point(data = chl_no_est, aes(x = event, y = result, color = station_name, group = station_name)) +
  geom_hline(yintercept = c(150), linetype = "solid", color = "black", linewidth = 0.7) +
  geom_text(data = annotation_chl, aes(x = x, y = y, label = label), nudge_x = 0.1) +
  scale_color_viridis(
    discrete = TRUE, name = NULL,
    guide = guide_legend(order = 1)
  ) +
  ggnewscale::new_scale_color() +
  geom_line(data = annotation_mean_chl, aes(
    x = event, y = avg_result,
    color = station_name,
    group = station_name,
  ), linetype = 2) +
  scale_color_viridis(
    discrete = TRUE, name = NULL,
    guide = guide_legend(order = 2)
  ) +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = 0.5),
    axis.title.x = element_blank(),
    legend.position = "bottom",
    legend.box = "vertical",
    legend.direction = "horizontal",
    panel.grid.major.y = element_line(size = .01, color = "grey60"),
    legend.margin = margin()
  ) +
  labs(y = "Chlorophyll a (mg/m2)") +
  scale_y_continuous(
    limits = c(0, 200), breaks = seq(0, 200, by = 20),
    expand = c(0, 0)
  )

enter image description here

更详细的方法是使用自定义键字形函数,该函数结合了两个

segmentsGrob
pointsGrob
来消除重复的标签。此外,这需要为
show.legend=FALSE
和第二个
geom_point
设置
geom_line

draw_key_cust <- function(data, params, size) {
  if (is.null(data$linetype)) {
    data$linetype <- 0
  } else {
    data$linetype[is.na(data$linetype)] <- 0
  }
  grob1 <- grid::segmentsGrob(
    0.1, 0.75, 0.9, 0.75,
    gp = grid::gpar(
      col = data$colour,
      lwd = .8 * .pt,
      lty = 1
    )
  )

  grob2 <- grid::segmentsGrob(
    0.1, 0.25, 0.9, 0.25,
    gp = grid::gpar(
      col = data$colour,
      lwd = .7 * .pt,
      lty = 2
    )
  )

  data$shape <- 19
  stroke_size <- data$stroke %||% 0.5
  stroke_size[is.na(stroke_size)] <- 0
  grob3 <- grid::pointsGrob(0.5, 0.75,
    pch = data$shape,
    gp = grid::gpar(
      col = data$colour,
      fontsize = 1.5 * .pt + stroke_size * .stroke / 2,
      lwd = stroke_size * .stroke / 2
    )
  )

  grid::gList(
    grob1,
    grob2,
    grob3
  )
}

ggplot(chl_no_est, aes(x = event, y = result, color = station_name, group = station_name)) +
  geom_line(
    linewidth = 0.8,
    key_glyph = "cust"
  ) +
  geom_point(
    show.legend = FALSE
  ) +
  geom_hline(yintercept = c(150), linetype = "solid", color = "black", linewidth = 0.7) +
  geom_text(
    data = annotation_chl, aes(x = x, y = y, label = label), nudge_x = 0.1,
    inherit.aes = FALSE
  ) +
  scale_color_viridis(
    discrete = TRUE, name = NULL,
    guide = guide_legend(order = 1)
  ) +
  geom_line(data = annotation_mean_chl, aes(
    y = avg_result
  ), linetype = 2, show.legend = FALSE) +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = 0.5),
    axis.title.x = element_blank(),
    legend.position = "bottom",
    legend.box = "vertical",
    legend.direction = "horizontal",
    panel.grid.major.y = element_line(size = .01, color = "grey60"),
    legend.margin = margin()
  ) +
  labs(y = "Chlorophyll a (mg/m2)") +
  scale_y_continuous(
    limits = c(0, 200), breaks = seq(0, 200, by = 20),
    expand = c(0, 0)
  )

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.