Сохранять или устанавливать соотношение между текстовыми метками и размером графика в grid.arrange

Я пытаюсь организовать 2 графика, созданные с помощью ggplot2, и хотел бы, чтобы графики были размером с квадрат и один рядом с другим, с общей легендой рядом с ними, так что изображение прекрасно вписывается в портретный стиль стр. Проблема в том, что когда я использую grid.arrange, чтобы расположить Grobs, метки и легенды становятся крошечными, а сюжетное пространство огромным.

Должно быть что-то, что мне не хватает в пакете grid.arrange, как команда, чтобы правильно установить все отношения, но я пробовал так много разных комбинаций размеров текста и пытался установить размеры графиков, но ничего похоже работа. Не могли бы вы мне помочь?

x1 <- c(10,20,30,40,50,60,70,80)
x2 <- c(20,40,60,80)
y1 <- c(10,30,100,30,20,40,20,10)
y2 <- c(20,60,20,30)
z1 <- c(1,1,1,2,2,2,2,2)
z2 <- c(2,2,1,2,1,2,1,2)
df1 <- data.frame(x=x1,y=y1, z=z1)
df2 <- data.frame(x=x2,y=y2, z=z1)

p1<-  ggplot(df1, aes(x=x,
     y=y,
     group=z,
     colour=z)) +
     geom_point() + theme_bw() +
     xlab("The size of this is tiny using grid.arrange")  +ylab("The size of this is tiny using grid.arrange") + ggtitle("A") + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), plot.title=element_text(size=16, hjust=0), axis.title = element_text(size=14), axis.text= element_text(size=12), legend.text= element_text(size = 12), legend.title = element_text(size = 12)) +
     geom_abline(intercept = 0, slope = 1) +
     xlim(0, 100) + ylim(0, 100) + guides(colour = guide_legend("\n This is a \n multi-line legend title", override.aes = list(size = 10)))

p2<-  ggplot(df2, aes(x=x,
     y=y,
     group=z,
     colour=z)) +
     geom_point() + theme_bw() +
     xlab("The size of this is tiny using grid.arrange")  +ylab("The size of this is tiny using grid.arrange") + ggtitle("B") + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), plot.title=element_text(size=16, hjust=0), axis.title = element_text(size=14), axis.text= element_text(size=12), legend.text= element_text(size = 12), legend.title = element_text(size = 12)) +
     geom_abline(intercept = 0, slope = 1) +
     xlim(0, 100) + ylim(0, 100) + guides(colour = guide_legend("\n This is a \n multi-line legend title", override.aes = list(size = 10)))

g_legend<-function(a.gplot){
tmp <- ggplot_gtable(ggplot_build(a.gplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)}

mylegend<-g_legend(p1)


pdf("my.figure.pdf", height = 20, width = 30) ## I have tried many different values for this too

grid.arrange(arrangeGrob(p1 + theme(legend.position="none"), # widths = unit(20, "cm"), heights = unit(20, "cm"),
p2 + theme(legend.position="none"), # widths = unit(20, "cm"),heights = unit(20, "cm"),
main = textGrob("The main figure title is also small and hard to align left",  hjust =0.6, gp = gpar(fontsize = 22)), nrow=1, heights=rep(10,10)), # widths = unit(10, "cm"),heights = unit(4, "cm")),
mylegend, widths=unit.c(unit(1, "npc") - sum(mylegend$width), sum(mylegend$width)), nrow=1)

dev.off()

Ответ 1

Добавьте theme() к каждому сюжету и задайте размер элементов, которые вы хотите изменить, например

theme( axis.text.x=element_text(size=20) ,  axis.title.x = element_text(size = 20 , colour = "red" ) )

enter image description here

Вы можете попытаться упорядочить объекты на странице сетки с помощью pushViewport, чтобы вручную настроить видовые экраны так, но вам, вероятно, придется немного поиграть с ним, чтобы получить его именно так, как вы хотите:

grid.newpage()
# Create a grid arangement of viewports to 'put' the plots into...
# widths and heights are normalised parent coordinates which scale from 0 to 1 with 1 being the entire width of the plot page
# The respect argument forces widths and heights to respect each other as they are set
pushViewport( viewport( layout = grid.layout( 2 , 3 , heights = unit( c( 0.02 , 0.45 ) , "npc" ) , widths = unit( c( 0.4 , 0.4 , 0.1 ) , "npc" ) , respect = matrix(rep(1,6),2) ) ) ) 
# We print plots to particular 'cells' on our page specified by the layout.pos.row and layout.pos.col
print( p1 + theme(legend.position="none") , vp = viewport( layout.pos.row = 2 , layout.pos.col = 1 ) )
print( p2 + theme(legend.position="none") , vp = viewport( layout.pos.row = 2, layout.pos.col = 2 ) )
# The grid.text is output to row one, and breaks across columns 1:2
grid.text("The main figure title is also small and hard to align left"  , just = "left" , x = unit(0.01, "npc"), y = unit(0.5, "npc"), vp = viewport( layout.pos.row = 1, layout.pos.col = 1:2) )
# We use upViewport to go up a level to the parent viewport
upViewport(0)
# We then define a new viewport for the legend which is a table grob.
# I had difficulty with this one so we set x and y coordinates and make it narrow but tall (0.1 npc width and 0.75 noc height)
vp3 <- viewport( width = unit(0.1,"npc") , height = unit(0.75 ,"npc") , x = 0.93, y = .5)
# We then activate this viewport
pushViewport(vp3)
# we output the legend which is a tableGrob to this viewport
grid.draw( mylegend )
popViewport()

Ответ 2

Я не уверен, что вы ожидаете от вывода, но попробуйте это,

g = arrangeGrob(
  arrangeGrob(p1 + coord_fixed() + theme(legend.position="none"),
              p2 + coord_fixed() +theme(legend.position="none"),
              main = textGrob("The main figure title is also small and hard to align left",  x=0, hjust =0, vjust=1, gp = gpar(fontsize = 22)), nrow=1), 
             mylegend, widths=unit.c(unit(1, "npc") - sum(mylegend$width), 
                                     sum(mylegend$width)), nrow=1)

ggsave("layout.pdf", g, width=12, height=5)