如何在同一个散点图上使用 geom_vline() 和 geom_hline 避免图例中的交叉效应?
Posted
技术标签:
【中文标题】如何在同一个散点图上使用 geom_vline() 和 geom_hline 避免图例中的交叉效应?【英文标题】:How to avoid the crossing effect in legend with geom_vline() and geom_hline on the same scatter plot? 【发布时间】:2021-04-24 03:34:08 【问题描述】:我用geom_hline()
和geom_vline()
创建了一个散点图,该图很好,但图例条目不是我想让它们出现的方式。 vline
(恢复)和hline
(阈值)在图例中相互交叉,令人困惑。我希望恢复图例条目为橙色垂直线,阈值图例条目为水平黑线。
我尝试了其他帖子中建议的几件事,使用 guide_legend(override.aes())
或 show.legend = F
但要么它更改了上面“类型”部分的图例条目(它删除了线条并保留了彩色圆圈),要么它只是删除了其中一行的图例条目。
这是我当前的代码:
ggplot(data = tst_formule[tst_formule$River != "Roya",], aes(x=Year, y = BRI_adi_moy_transect, shape = River, col = Type)) +
geom_point(size = 3) +
geom_errorbar(aes(ymin = BRI_adi_moy_transect - SD_transect, ymax = BRI_adi_moy_transect + SD_transect), width = 0.4) +
scale_shape_manual(values = c(15, 16, 17)) +
scale_colour_manual(values = c("chocolate1", "darkcyan")) +
geom_vline(aes(xintercept = Restauration_year, linetype = "Restoration"), colour = "chocolate1") +
geom_hline(aes(yintercept = 0.004, linetype = "Threshold"), colour= 'black') +
scale_linetype_manual(name = NULL, values = c(4, 5)) +
scale_y_continuous("BRI*", limits = c(min(tst_formule$BRI_adi_moy_transect - tst_formule$SD_transect),
max(tst_formule$BRI_adi_moy_transect + tst_formule$SD_transect))) +
scale_x_continuous(limits = c(min(tst_formule$Year - 1),max(tst_formule$Year + 1)), breaks = scales::breaks_pretty(n = 6)) +
theme_bw() +
facet_wrap(vars(River))
这是我的dput
数据:
structure(list(River = c("Durance", "Durance", "Durance", "Durance",
"Roya", "Var"), Reach = c("La Brillanne", "Les Mées", "La Brillanne",
"Les Mées", "Basse vallée", "Basse vallée"), Type = c("restaured",
"target", "restaured", "target", "witness", "restaured"), Year = c(2017,
2017, 2012, 2012, 2018, 2011), Restauration_year = c(2013, 2013,
2013, 2013, 2000, 2009), BRI_adi_moy_transect = c(0.0028, 0.0017,
0.0033, 0.0018, 0.009, 0.0045), SD_transect = c(0.00128472161839638,
0.000477209421076879, 0.00204050725984513, 0.000472466654940182,
0.00780731734792112, 0.00310039904793707)), row.names = c(NA,
6L), class = "data.frame")
知道如何让它做我想做的事吗?
【问题讨论】:
【参考方案1】:这是本期https://github.com/tidyverse/ggplot2/issues/2483中记录的一个已知问题
那里没有提供任何答案,除了自定义绘制的图例键,我认为这是不可能的
【讨论】:
【参考方案2】:我找到了一个令人难以置信的不可概括的解决方法,但我想我还是会分享。解决方法是编写键字形函数,根据线型有条件地输出键。这有点硬编码,所以我不知道如何概括这一点。下面是两个函数:
glyph_vline <- function(data, params, size)
if (data$linetype == 4)
draw_key_vline(data, params, size)
else
zeroGrob()
glyph_hline <- function(data, params, size)
if (data$linetype == 5)
draw_key_path(data, params, size)
else
zeroGrob()
您需要将这些输入到 vline/hline 层的 key_glyph
参数中。像这样:
ggplot(data = tst_formule[tst_formule$River != "Roya",], aes(x=Year, y = BRI_adi_moy_transect, shape = River, col = Type)) +
geom_point(size = 3) +
geom_errorbar(aes(ymin = BRI_adi_moy_transect - SD_transect, ymax = BRI_adi_moy_transect + SD_transect), width = 0.4) +
scale_shape_manual(values = c(15, 16, 17)) +
scale_colour_manual(values = c("chocolate1", "darkcyan")) +
geom_vline(aes(xintercept = Restauration_year, linetype = "Restoration"),
colour = "chocolate1", key_glyph = glyph_vline) +
geom_hline(aes(yintercept = 0.004, linetype = "Threshold"),
colour= 'black', key_glyph = glyph_hline) +
scale_linetype_manual(name = NULL, values = c(4, 5)) +
scale_y_continuous("BRI*", limits = c(min(tst_formule$BRI_adi_moy_transect - tst_formule$SD_transect),
max(tst_formule$BRI_adi_moy_transect + tst_formule$SD_transect))) +
scale_x_continuous(limits = c(min(tst_formule$Year - 1),max(tst_formule$Year + 1)), breaks = scales::breaks_pretty(n = 6)) +
theme_bw() +
facet_wrap(vars(River))
【讨论】:
【参考方案3】:创建两个线型比例。我已将 vline/hline 调用置于底部以获得更好的可见性。
library(tidyverse)
library(ggnewscale)
ggplot(data = tst_formule[tst_formule$River != "Roya",], aes(x=Year, y = BRI_adi_moy_transect, shape = River, col = Type)) +
geom_point(size = 3) +
geom_errorbar(aes(ymin = BRI_adi_moy_transect - SD_transect, ymax = BRI_adi_moy_transect + SD_transect), width = 0.4) +
scale_shape_manual(values = c(15, 16, 17)) +
scale_colour_manual(values = c("chocolate1", "darkcyan")) +
scale_y_continuous("BRI*", limits = c(min(tst_formule$BRI_adi_moy_transect - tst_formule$SD_transect),
max(tst_formule$BRI_adi_moy_transect + tst_formule$SD_transect))) +
scale_x_continuous(limits = c(min(tst_formule$Year - 1),max(tst_formule$Year + 1)), breaks = scales::breaks_pretty(n = 6)) +
theme_bw() +
facet_wrap(vars(River)) +
# here starts the trick
geom_vline(aes(xintercept = Restauration_year, linetype = "Restauration"), colour = "chocolate1") +
scale_linetype_manual(name = NULL, values = 4) +
# ggnewscale is an amazing package
new_scale("linetype") +
# now do the same for geom_hline
geom_hline(aes(yintercept = 0.004, linetype = "Threshold"), colour= 'black') +
scale_linetype_manual(name = NULL, values = 5)
【讨论】:
谢谢@tjebo!那很完美!知道为什么vline
和 hline
的图例条目现在位于图例的顶部吗?有没有办法让它们保持在全局图例的底部,并使它们之间的空间更小?
@Jude 我原以为你会问这个问题......在这种情况下很棘手。我想很难改变只有这两个传说项目之间的距离而不弄乱grobs。图例间距可能是一个相当大的挑战。 ***.com/questions/11366964/… 可能会有所帮助。至于订单***.com/q/11393123/7941188
这可能值得一个后续问题,例如“更改仅选定图例之间的间距”左右,我认为之前已经问过,但我没有在快速搜索中找到它。跨度>
我设法通过theme(legend.spacing.y())
和guides()
实现了我想要的形状、颜色和线条,因此效果很好。感谢您的帮助!以上是关于如何在同一个散点图上使用 geom_vline() 和 geom_hline 避免图例中的交叉效应?的主要内容,如果未能解决你的问题,请参考以下文章