在使用arrangeGrob时是否可以裁剪绘图区域?

3

我有一个类似于以下情况的用例,其中我创建多个图表并使用gridExtra将它们排列成某些页面布局,最后使用ggsave将其保存为PDF:

p1 <- generate_ggplot1(...)
p2 <- generate_ggplot2(...)

final <- gridExtra::arrangeGrob(p1, p2, ...)
ggplot2::ggsave(filename=output.file,plot=final, ...)

在使用arrangeGrob将图表p2放入页面布局时,是否可能对其进行裁剪?问题在于,p2顶部和底部有很多额外的空间,我想要摆脱它们,由于使用ggplot2时无法进行cropping,所以我在想,在排列时是否可以裁剪它...

更新这里是一个自包含的示例,我想通过任何方式消除红色标注的区域:

library(ggplot2); library(dplyr); library(stringr); library(gridExtra)

df <- data.frame(group = c("Cars", "Trucks", "Motorbikes"),n = c(25, 25, 50),
                 label2=c("Cars are blah blah blah", "Trucks some of the best in town", "Motorbikes are great if you ..."))
df$ymax = cumsum(df$n)
df$ymin = cumsum(df$n)-df$n
df$ypos = df$ymin+df$n/2
df$hjust = c(0,0,1)

p1 <- ggplot(mtcars,aes(x=1:nrow(mtcars),y=mpg)) + geom_point()

p2 <- ggplot(df %>%
         mutate(label2 = str_wrap(label2, width = 10)), #change width to adjust width of annotations
       aes(x="", y=n, fill=group)) +
  geom_rect(aes_string(ymax="ymax", ymin="ymin", xmax="2.5", xmin="2.0")) +
  expand_limits(x = c(2, 4)) + #change x-axis range limits here
  # no change to theme
  theme(axis.title=element_blank(),axis.text=element_blank(),
        panel.background = element_rect(fill = "white", colour = "grey50"),
        panel.grid=element_blank(),
        axis.ticks.length=unit(0,"cm"),axis.ticks.margin=unit(0,"cm"),
        legend.position="none",panel.spacing=unit(0,"lines"),
        plot.margin=unit(c(0,0,0,0),"lines"),complete=TRUE) +
  geom_text(aes_string(label="label2",x="3",y="ypos",hjust="hjust")) +
  coord_polar("y", start=0) +
  scale_x_discrete()

final <- arrangeGrob(p1,p2,layout_matrix = rbind(c(1),c(2)),
                     widths=c(4),heights=c(4,4), padding=0.0,
                     respect=TRUE, clip="on")
plot(final)

输出结果如下:

arrangeGrob 输出


在使用arrangeGrob排列之前,使用theme修改绘图边距怎么样? - mikeck
我知道,但这还不够,看看这个问题的答案,那里就出现了问题:https://stackoverflow.com/questions/45817032/how-to-fit-custom-long-annotations-geom-text-inside-plot-area-for-a-donuts-plot 我已经尝试了我能想到的一切来消除垂直空间,但迄今为止没有成功。 - SkyWalker
我认为gridextra可能有一些负边距来裁剪绘图区域,同时将其放置在布局中或者调整视口以达到此目的。 - SkyWalker
3
您能提供两个示例图的数据和代码吗?我们需要这些来进行工作。 - eipi10
1个回答

2
为此,需要一个多部分的解决方案。
首先,在单个图形中更改边距,可以使用theme()中的plot.margin,这是一种方便的方法。但是,如果目标是组合多个图形,则仅靠这个还不足以解决问题。
要做到这一点,您需要结合使用plot.margin和arrangeGrob()中的特定绘图顺序。您需要一个特定的顺序,因为绘图按照您调用它们的顺序打印,因此,更容易更改位于其他绘图后面的绘图的边距,而不是在绘图前面。我们可以将其想象成通过在我们要缩小的绘图上展开另一个绘图来覆盖我们想要缩小的绘图边距。请参见下面的图形以进行说明:
在设置plot.margin之前:

enter image description here

#Main code for the 1st graph can be found in the original question.

在设置了 plot.margin 之后:

enter image description here

#Main code for 2nd graph:
ggplot(df %>%
           mutate(label2 = str_wrap(label2, width = 10)),
                  aes(x="", y=n, fill=group)) +
  geom_rect(aes_string(ymax="ymax", ymin="ymin", xmax="2.5", xmin="2.0")) +
  geom_text(aes_string(label="label2",x="3",y="ypos",hjust="hjust")) +
  coord_polar(theta='y') +
  expand_limits(x = c(2, 4)) + 
  guides(fill=guide_legend(override.aes=list(colour=NA))) +
  theme(axis.line = element_blank(),
        axis.ticks=element_blank(),
        axis.title=element_blank(),
        axis.text.y=element_blank(),
        axis.text.x=element_blank(),
        panel.border = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_rect(fill = "white"),
        plot.margin = unit(c(-2, 0, -2, -.1), "cm"),
        legend.position = "none") +
 scale_x_discrete(limits=c(0, 1))

在组合 plot.margin 设置和 arrangeGrob() 重新排序之后:

enter image description here

#Main code for 3rd graph:
p1 <- ggplot(mtcars,aes(x=1:nrow(mtcars),y=mpg)) + geom_point()

p2 <- ggplot(df %>%
               mutate(label2 = str_wrap(label2, width = 10)), #change width to adjust width of annotations
                      aes(x="", y=n, fill=group)) +
        geom_rect(aes_string(ymax="ymax", ymin="ymin", xmax="2.5", xmin="2.0")) +
        geom_text(aes_string(label="label2",x="3",y="ypos",hjust="hjust")) +
        coord_polar(theta='y') +
        expand_limits(x = c(2, 4)) + #change x-axis range limits here
        guides(fill=guide_legend(override.aes=list(colour=NA))) +
        theme(axis.line = element_blank(),
              axis.ticks=element_blank(),
              axis.title=element_blank(),
              axis.text.y=element_blank(),
              axis.text.x=element_blank(),
              panel.border = element_blank(),
              panel.grid.major = element_blank(),
              panel.grid.minor = element_blank(),
              panel.background = element_rect(fill = "white"),
              plot.margin = unit(c(-2, 0, -2, -.1), "cm"),
              legend.position = "none") +
        scale_x_discrete(limits=c(0, 1))

final <- arrangeGrob(p2,p1,layout_matrix = rbind(c(1),c(2)),
                     widths=c(4),heights=c(2.5,4),respect=TRUE)

请注意,在最终代码中,我将arrangeGrob中的顺序从p1、p2反转为p2、p1。然后我调整了第一个绘制对象的高度,这是我们想要缩小的对象。这个调整允许先前的plot.margin调整生效,随着它的生效,按顺序打印的图形(即P1)将开始占据原来是P2边距的空间。如果您只做其中一项调整而不做其他调整,则解决方案将无法正常工作。每一步都很重要,才能产生上面的最终结果。

我曾经害怕不得不动手修改gridExtra及其相关的内容:D - SkyWalker

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