如何在 ggplot2 中独立于轴标签指定图形的大小

How to specify the size of a graph in ggplot2 independent of axis labels

说我有一个数据框,想画一个图

df <- melt(iris)

p <- ggplot(data = df, aes(x = Species, y = value)) + 
       geom_boxplot() + theme(aspect.ratio = 1)

然后我想使用 ggsave() 保存此图的 pdf

ggsave(plot = p, width = 3, height = 3, dpi = 300, filename = "not squished axis.pdf")

问题是我想指定图本身的尺寸但独立于轴标签,以便下面指定的图在轴的绝对长度方面具有相同的大小和尺寸。

q <- ggplot(data = df, aes(x = Species, y = (value)*10000000)) +
       geom_boxplot() + theme(aspect.ratio = 1)

ggsave(plot = q, width = 3, height = 3, dpi = 300, filename = "squished axis.pdf")

有没有办法轻松做到这一点?

这是一个在轴长度方面更接近我想要的图的示例:

唯一的问题是,通过改变纵横比,我最终挤压了 y 轴,使 x 轴的长度更接近均匀...

我不太明白你在追求什么,所以这有点摸不着头脑。

您可以使用相同比例显示两个图 facet_wrap:

# Your sample data
df <- list(
    one = melt(iris),
    two = with(melt(iris), cbind.data.frame(Species, variable, value * 1000)));
df <- melt(df);

ggplot(df, aes(x = Species, y = value)) + 
    geom_boxplot() + theme(aspect.ratio = 1) + 
    facet_wrap(~ L1);

或者允许每个方面的 y 尺度自由变化。

ggplot(df, aes(x = Species, y = value)) + 
    geom_boxplot() + theme(aspect.ratio = 1) + 
    facet_wrap(~ L1, scales = "free_y");

您可以通过使用 nrowncol 指定列数或行数来调整构面的网格布局。

因此,例如,对于两个图的垂直放置,您可以这样做

ggplot(df, aes(x = Species, y = value)) + 
    geom_boxplot() + theme(aspect.ratio = 1) + 
    facet_wrap(~ L1, ncol = 1, scales = "free_y");

使用ggplotGrob。像这样:

g1 <- ggplot(...)
g2 <- ggplot(...)

g1grob <- ggplotGrob(g1)
g2grob <- ggplotGrob(g2)

grid.arrange(g1grob, g2grob)

我观察到相同的行为,当在 x 轴上使用垂直标签时,这种行为会被放大。

使用以下代码,绘图区域会因标签长度的不同而有所不同。

library(ggplot2)
library(gridExtra)


df1 <- data.frame(x_label=c(rep("one", 10), rep("two", 20), rep("three", 30))) 

plt1 <- ggplot(data.frame(df1), aes(x=x_label)) +
  ggtitle("My test data percentages") + 
  labs(x="", y="Percentage" ) + 
  geom_bar(aes(y = ( (..count..)/sum(..count..) * 100.0) ), width=1) +
  expand_limits(y=c(0.0, 50.0)) +
  theme_light() +
  theme(plot.title = element_text(hjust = 0.5), axis.text.x=element_text(angle=90, hjust=1, size=8), panel.spacing.x=unit(0.5, "lines")) 

df2 <- data.frame(x_label=c(rep("very long label one", 10), rep("very long label two", 20), rep("very long label three", 30))) 

plt2 <- ggplot(data.frame(df2), aes(x=x_label)) +
  ggtitle("My test data percentages") + 
  labs(x="", y="Percentage" ) + 
  geom_bar(aes(y = ( (..count..)/sum(..count..) * 100.0) ), width=1) +
  expand_limits(y=c(0.0, 50.0)) +
  theme_light() +
  theme(plot.title = element_text(hjust = 0.5), axis.text.x=element_text(angle=90, hjust=1, size=8), panel.spacing.x=unit(0.5, "lines")) 

gridExtra::grid.arrange(plt1, plt2, nrow=1)

绘图区域随标签长度变化

回答你的问题有点晚,但我认为这个 post 可能会有所帮助:ggplot2, arrange multiple plots, all the same size, no gaps in between

所以基本上您希望多个图形的绘图区域(x 轴和 y 轴内的区域)相同。这也是我在使用 ggplot2 时发现的一个问题。一种解决方案是通过 cowplot 包中的 align_plots() 函数传递每个图:

`allplotslist <- align_plots(plot1, plot2, plot3, align = "hv")`

这使得所有绘图的绘图区域大小相同。 然后您可以使用 ggdraw() (也来自 cowplot)将绘图放入同一个图中,指定每个绘图的坐标,并将大小指定为(x 坐标,y 坐标,宽度,高度):

`final_figure <- ggdraw() + draw_plot(allplotslist[[1]], 0,0,0.3,0.3) + 
draw_plot(allplotslist[[2]], 0,0.3,0.3,0.3) + draw_plot(allplotslist[[3]], 0,0,0.6,0.3)`

您还可以使用其他函数,如 plot_grid()(来自 cowplot)或 grid.arrange()(来自 gridExtra 包)来绘制大小相同的新图:

`grid.arrange(allplotslist[[1]], allplotslist[[2]], allplotslist[[3]])`

希望对您有所帮助, 干杯

我觉得有点晚了,但我通过修复标签的 nchar 解决了这个问题。 这不是一个非常通用的解决方案,我知道。我需要 30 个(或更多)分离图。在单独的底层 grob 中的观察数量,因此 x 轴的大小必须固定。 希望这会对某人有所帮助