防止第二个 aes() 覆盖 ggplot2 中轴的范围(ylim,xlim)

prevent a second aes() to override the range of the axes (ylim, xlim) in ggplot2

我有不同类型产品随时间变化的价格。我想在一个 sheet 中可视化不同价格的演变,所以我使用了多面 ggplot。这是我的玩具示例:

df1 <- data.frame(time = rep(1:100, times = 5), 
                  type = rep(c("A", "B", "C", "D", "E"), each = 100), 
                  price = rnorm(n = 500, mean = 100))

gp <- ggplot(data = df1, aes(x = time, y = price))
# scales free because the price level of each product may be different
gp <- gp + facet_wrap(~type, nrow = 3, ncol = 2, scales = "free")
gp <- gp + geom_point() + geom_line()
gp

这会产生我想要的情节:

我也有每种产品的参考价格(在不同的数据集中),我想在图中指出这些价格。所以我使用 geom_hline() 如下:

df2 <- data.frame(type = c("A", "B", "C", "D", "E"), 
                  refprice = c(100, 105, 95, 50, 40))
gp <- gp + geom_hline(data = df2, aes(yintercept = refprice), facets = ~type)

它有效,但它可以显着改变 y 轴的范围,我不希望那样。我想保留第一部分自动生成的 ylim ,以便正确可视化价格的演变,而不管参考价格如何(如果参考价格不是相对的,可以不看到参考价格)接近实际价格)。

我知道我可以使用 scale_y_continuous()coord_cartesian() 或简写 ylim() 来手动设置我想要的限制,但我不喜欢这种替代方法,因为两者都需要硬-对限制进行编码或编码过多以计算适当的限制。所以我认为 ggplot 中必须有一种更简单、更优雅的方法来避免第二次调用覆盖 ylims,而是利用第一次调用中生成的 ylims。

我一直在(我认为,彻底地)寻找这个问题的解决方案(SO,google,rseek,),我找到的所有解决方案都涉及我刚才所说的我不喜欢的解决方案。所以我决定在这里 post 看看是否有人知道 ggplot2 中的一些隐藏(或不是那么隐藏)的功能,以使其更容易和更优雅。非常感谢。

yrange <- sapply(ggplot_build(gp)$panel$ranges, function(x) x$y.range)
#order df2 correctly (the same order as the panels) if it isn't

gp + geom_hline(data = df2[df2$refprice >= yrange[1,] & df2$refprice <= yrange[2,],], 
                aes(yintercept = refprice))