使用ggplot将柱形图的列与折线图的点对齐

4

在使用ggplot绘制具有相同x轴的折线图和条形图时,是否有一种方法可以使折线图的点与条形图的条对齐?以下是我试图使用的样本数据。

library(ggplot2)
library(gridExtra)

data=data.frame(x=rep(1:27, each=5), y = rep(1:5, times = 27))
yes <- ggplot(data, aes(x = x, y = y))
yes <- yes + geom_point() + geom_line()

other_data = data.frame(x = 1:27, y = 50:76  )

no <- ggplot(other_data, aes(x=x, y=y))
no <- no + geom_bar(stat = "identity")

grid.arrange(no, yes)

这里是输出结果:

输入图像说明

线状图的第一个点位于第一条柱形图的左侧,而线状图的最后一个点位于最后一条柱形图的右侧。

感谢您的时间。


我不确定我理解你想做什么。问题在于条形图有宽度,而点没有。因此,第一根条的左边缘位于(大约)x=0.5处,最后一根条的右边缘位于x=27.5处。第一个和最后一个点位于x=1和x=27。因此,对齐点和条的边缘似乎非常不自然,因为这意味着两个轴的比例不同。将条的中心与点对齐会更有意义,不是吗? - Stibu
如何将条形图的中心与点对齐? - JakeC
查看tracks包,这里有一个例子 - zx8754
2个回答

2

在@Stibu的帖子基础上进行扩展:要使绘图对齐,请使用gtable(或参见您之前的问题的答案)。

library(ggplot2)
library(gtable)

data=data.frame(x=rep(1:27, each=5), y = rep(1:5, times = 27))
yes <- ggplot(data, aes(x = x, y = y))
yes <- yes + geom_point() + geom_line() + 
   scale_x_continuous(limits = c(0,28), expand = c(0,0))

other_data = data.frame(x = 1:27, y = 50:76  )

no <- ggplot(other_data, aes(x=x, y=y))
no <- no + geom_bar(stat = "identity") + 
   scale_x_continuous(limits = c(0,28), expand = c(0,0))

gYes = ggplotGrob(yes)   # get the ggplot grobs
gNo = ggplotGrob(no)

plot(rbind(gNo, gYes, size = "first"))   # Arrange and plot the grobs

这里输入图片描述

编辑 要更改绘图的高度:

g = rbind(gNo, gYes, size = "first")  # Combine the plots
panels <- g$layout$t[grepl("panel", g$layout$name)] # Get the positions for plot panels
g$heights[panels] <- unit(c(0.7, 0.3), "null") # Replace heights with your relative heights
plot(g)

有没有办法改变绘图的高度,使得第二个图的高度小于第一个图的高度?类似于在grid.arrange()中使用heights = c(0.7,0.3)的方式。 - JakeC
请参考此答案此答案。另外,我已经添加了一个编辑。 - Sandy Muspratt

1

我可以想到(至少)两种方法来对齐两个图中的x轴:

  1. The two axis do not align because in the bar plot, the geoms cover the x-axis from 0.5 to 27.5, while in the other plot, the data only ranges from 1 to 27. The reason is that the bars have a width and the points don't. You can force the axex to align by explicitly specifying an x-axis range. Using the definitions from your plot, this can be achieved by

    yes <- yes + scale_x_continuous(limits=c(0,28))
    no <- no + scale_x_continuous(limits=c(0,28))
    grid.arrange(no, yes)
    

    limits sets the range of the x-axis. Note, though, that the alginment is still not quite perfect. The y-axis labels take up a little more space in the upper plot, because the numbers have two digits. The plot looks as follows: enter image description here

  2. The other solution is a bit more complicated but it has the advantage that the x-axis is drawn only once and that ggplot makes sure that the alignment is perfect. It makes use of faceting and the trick described in this answer. First, the data must be combined into a single data frame by

    all <- rbind(data.frame(other_data,type="other"),data.frame(data,type="data"))
    

    and then the plot can be created as follows:

    ggplot(all,aes(x=x,y=y)) + facet_grid(type~.,scales = "free_y") +
       geom_bar(data=subset(all,type=="other"),stat="identity") +
       geom_point(data=subset(all,type=="data")) +
       geom_line(data=subset(all,type=="data"))
    

    The trick is to let the facets be constructed by the variable type which was used before to label the two data sets. But then each geom only gets the subset of the data that should be drawn with that specific geom. In facet_grid, I also used scales = "free_y" because the two y-axes should be independent. This plot looks as follows:

enter image description here

您可以在定义数据框“all”时通过指定其他名称来更改facet的标签。如果您想要完全删除它们,则可以将以下内容添加到您的图表中:
+ theme(strip.background = element_blank(), strip.text = element_blank())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接