双 Y 轴与 facet_wrap 结合使用

4
如何在ggplot2中将转换比例尺放在右侧中,演示了通过操作和合并ggplot2对象与gtable来添加同一图中的两个y轴的方法。从那里的例子中,我设法将其扩展为适用于facet_wrap。请参见下面的示例。
然而,有三件事情不完美。
  1. 标度始终放在最右边。如果与最后一行的图形连接会更好
  2. 如果所有绘图都单独具有y轴(即您在facet_wrap中放置了scales="free_y"),它将无效。
  3. 如果我保留网格线(被注释的线),第二个图形的网格线会出现在第一个图形的前面。
任何想法是否有聪明的方式解决这些小问题?
library(ggplot2)
library(gtable)
library(grid)

p1 <- ggplot(diamonds, aes(y=carat,x=price))
p1 <- p1 + geom_point(color="red")
p1 <- p1 + facet_wrap(~ color)
p1 <- p1 + theme_bw()  %+replace%  theme(panel.background = element_rect(fill = NA)) # use white theme and set bg to transparent so they can merge nice
#p1 <- p1 + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) # remove gridlines
p1


p2 <- ggplot(diamonds, aes(x=price))
p2 <- p2 + geom_histogram( binwidth = 1000)
p2 <- p2 +  facet_wrap(~ color)
p2 <- p2 + theme_bw()  %+replace%  theme(panel.background = element_rect(fill = NA))
#p2 <- p2 + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())

p2



## Putting plots together ##################
# extract gtable
g1 <- ggplot_gtable(ggplot_build(p1))
g2 <- ggplot_gtable(ggplot_build(p2))

# overlap the panel of 2nd plot on that of 1st plot
pp <- c(subset(g1$layout, grepl("panel",name) , se = t:r))
g <- gtable_add_grob(g1, g2$grobs[grep("panel",g2$layout$name)], pp$t, 
                     pp$l, pp$b, pp$l)



# axis tweaks
ia <- which(grepl("axis_l",g2$layout$name) |  grepl("axis-l",g2$layout$name)     )
ga <- g2$grobs[ia]


axis_idx <- as.numeric(which(sapply(ga,function(x) !is.null(x$children$axis))))

for(i in 1:length(axis_idx)){
  ax <- ga[[axis_idx[i]]]$children$axis
  ax$widths <- rev(ax$widths)
  ax$grobs <- rev(ax$grobs)
  ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
  g <- gtable_add_cols(g, g2$widths[g2$layout[ia[axis_idx[i]], ]$l], length(g$widths) - 1)
  g <- gtable_add_grob(g, ax, pp$t[axis_idx[i]], length(g$widths) - i, pp$b[axis_idx[i]])
}



# Plot!
grid.newpage()
grid.draw(g)

facet_wrap with dual axis

1个回答

1
这是一个你应该能够进一步调整以满足自己需求的修改。要想得到更精确和通用的结果需要我花费比现在更多的时间。但我认为你不会有困难去进行额外的调整。
前几步没有改变。
这里我复制了你的程序,用于前两个行面板,但没有添加底部调整过的轴。
# do not add back the bottom lhs axis
for(i in 1:(length(axis_idx)-1)) {
    ax <- ga[[axis_idx[i]]]$children$axis
    ax$widths <- rev(ax$widths)
    ax$grobs <- rev(ax$grobs)
    ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
    g <- gtable_add_cols(g, 
        g2$widths[g2$layout[ia[axis_idx[i]], ]$l], length(g$widths) - 1)
    g <- gtable_add_grob(g, 
        ax, pp$t[axis_idx[i]], length(g$widths) - i, pp$b[axis_idx[i]])
}

这里我单独处理底部行。这部分还没有泛化。您需要稍微调整刻度和垂直轴之间的距离。您还需要将索引泛化以适应仅存在一个底部图、2个图等情况。

# Here I fix the index ``i`` to 3, to cater for your example.
i <- length(axis_idx)
    ax <- ga[[axis_idx[i]]]$children$axis
    ax$widths <- rev(ax$widths)
    ax$grobs <- rev(ax$grobs)
    ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
    g <- gtable_add_cols(g, g2$widths[3], 12)
    g <- gtable_add_grob(g, ax, pp$t[axis_idx[i]], length(g$widths) - 9, pp$b[axis_idx[i]])

需要泛化的位是数字12和9。可能需要调整的位是带有unit(0.15, "cm")的行,以获得比目前更多的空间。
首先,您的g对象具有宽度12,这是3乘3面板加上3个垂直轴。然后您添加了一列来适应第二个轴,从而获得宽度为15。选择数字12是为了放在底部图的右侧。选择数字9是为了将第二个轴放置在那里。我想。

enter image description here


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