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

时间:2015-01-22 09:47:01

标签: r ggplot2

我有不同类型产品的价格。我想在一张纸上可视化不同价格的演变,所以我使用了一个刻面的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

这会产生我想要的情节:

enter image description here

我也有每种产品的参考价格(在不同的数据集中),我想在图中标明这些价格。所以我使用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)

enter image description here

它有效,但它可以大大改变y轴的范围,我不希望这样。我希望将ylim保留为第一部分自动生成的,以便无论参考价格如何,都可以正确显示价格的变化(如果是参考价格,则可以不查看参考价格不太接近实际价格。)

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

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

1 个答案:

答案 0 :(得分:1)

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))

resulting plot