我有一个 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)
没有,不确定如何继续。
一个快速简单的选择是使用
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)
)
更详细的方法是使用自定义键字形函数,该函数结合了两个
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)
)