首先,简短的回答是...BLUF或更时髦的TL;DR(继续阅读,看看我是如何做到的).
这不是一场完美的比赛.但是,您可以根据需要或需要进行调整,以实现所需的输出.
library(grid)
g3 <- ggplotGrob(g2)
bW <- list() # to collect the "before" width
bX <- list() # to collect the "before" x position start of column
invisible(lapply(1:length(g3),
function(j) {
if(length(g3$grobs[[j]]$children) > 5) {
i <- g3$grobs[[j]]$children
k <- i[grepl("rect", names(i))] %>%
gsub("^.*\\[(.*)\\].", "\\1", .)
bW[length(bW) + 1] <<- list(setNames(i[[k]]$width[[1]], k))
bX[length(bX) + 1] <<- list(setNames(list(c(i[[k]]$x)), k))
}
}))
bW <- unlist(bW) # before widths
bw <- min(bW) * 2 # new width of third facet's columns
g3$grobs[[4]]$children[[names(bW)[3]]]$width[[1]] <- unit(bw, "native")
g3$grobs[[4]]$children[[names(bW)[3]]]$width[[2]] <- unit(bw, "native")
# new x start position to accommodate wider columns
g3$grobs[[4]]$children[[names(bW)[3]]]$x[[1]] <- unit(flatten(bX)[[1]][[1]], "native")
g3$grobs[[4]]$children[[names(bW)[3]]]$x[[2]] <- unit(flatten(bX)[[1]][[3]], "native")
# close up unused space
g3$widths[[9]] <- unit(1.1, "null")
grid.draw(g3)
你可以使用grid
号图书馆.
首先,为网格库创建一个Grob对象.
library(grid)
library(tidyverse)
g3 <- ggplotGrob(g2)
你将有三个gTree
格罗布,因为在这个格罗布中有三个地块.
因为您有列和点,所以我查找了名称包含geom_rect
和geom_point
的子项的Grobs.一旦我找到了一个,我就计算了子元素的数量,并用这个数字来寻找其他的子元素.面板(背景)和gTree
将至少有另一个子项.在本例中,每个GROB地块实际上有6个子代.
所以你知道,这lapply
是迭代构建的,在我找到我要找的东西后,我必须与Grob合作来找出如何访问不同的元素.(如果您try 将其应用于不同的数据或不同的图表,了解它是如何构建的可能会很有用.)
此代码创建一列列宽度和列在x轴上的位置,该列需要以指定的单位开始.
bW <- list() # to collect the "before" width
bX <- list() # to collect the "before" x position start of column
invisible(lapply(1:length(g4),
function(j) {
if(length(g4[[j]]$children) > 5) { # grobs with more than 5 kids
i <- g4[[j]]$children # extract children
k <- i[grepl("rect", names(i))] %>% # get name
gsub("^.*\\[(.*)\\].", "\\1", .)
message("results of k ", k, " for ", j)
message("width is ")
message(print(i[[k]]$width))
message("x is ")
message(print(i[[k]]$x))
# capture before widths and x positions
bW[length(bW) + 1] <<- list(setNames(i[[k]]$width[[1]], k))
bX[length(bX) + 1] <<- list(setNames(list(c(i[[k]]$x)), k))
}
}))
对于列宽的"之前"列表,我想要最小值&;2.列的大小是相对于绘图宽度的,因此如果我们要减少未使用的绘图空间,您需要首先使列更宽.我用的是4栏图的列宽乘以2.然而,如果你理解相对性质,这就不是很完美了.(这将"接近"你想要的.)
由于有两列,因此需要为每一列指定带单位的宽度.最重要的是...判断你所期待的.
bW <- unlist(bW)
# geom_rect.rect.11892 geom_rect.rect.11894 geom_rect.rect.11896
# 0.1840909 0.1840909 0.2045455
bw <- min(bW) * 2 # new column width, before rendering plot more narrow
# [1] 0.3681818
g3$grobs[[4]]$children[[names(bW)[3]]]$width # before
# [1] 0.204545454545455native 0.204545454545455native
g3$grobs[[4]]$children[[names(bW)[3]]]$width[[1]] <- unit(bw, "native")
g3$grobs[[4]]$children[[names(bW)[3]]]$width[[2]] <- unit(bw, "native")
g3$grobs[[4]]$children[[names(bW)[3]]]$width # after
# [1] 0.368181818181818native 0.368181818181818native
如果我们让它这样,柱子就不会再居中了.这就是为什么我们还收集了x
个.
到目前为止,情况看起来是这样的.
每列都将有一个值为x
.所以实际上,我们想从第一列和第三列开始,从前两个方面开始.
flatten(bX)
# $geom_rect.rect.12931
# [1] 0.07840909 0.28295455 0.53295455 0.73750000
#
# $geom_rect.rect.12933
# [1] 0.07840909 0.28295455 0.53295455 0.73750000
#
# $geom_rect.rect.12935
# [1] 0.1704545 0.6250000
#
g3$grobs[[4]]$children[[names(bW)[3]]]$x # before
# [1] 0.170454545454545native 0.625native # use the first plot, 1st column position
g3$grobs[[4]]$children[[names(bW)[3]]]$x[[1]] <- unit(flatten(bX)[[1]][[1]], "native")
# use the first plot, 3rd column position
g3$grobs[[4]]$children[[names(bW)[3]]]$x[[2]] <- unit(flatten(bX)[[1]][[3]], "native")
g3$grobs[[4]]$children[[names(bW)[3]]]$x # after
# [1] 0.0784090909090909native 0.532954545454545native
现在,柱子居中.
现在它们变宽了,居中了,我们可以改变这个地块的面积了.记住...这都是相对的大小.
您可以看到这样的宽度:
g3$widths
但是输出是没有意义的!我能说的最好的方法是,你可以通过另外两个电话来理解它所告诉你的东西.当您在第一行代码中调用布局时,您将获得一个值的表,它可能没有太大意义,而从第二个调用中获得的是一个表,表明它是如何分解的.例如,您将在第三个面所在的空间中看到8-9
个.在每个面的顶部和底部,您将看到2.2null
.这是我们需要改变的尺寸.
g3$layout
gtable::gtable_show_layout(g3)
现在我们知道每个图都是2.2null
,我们可以返回到宽度输出,并查找第三次调用2.2null
.由于您需要大约一半的空间,对于一半的列,我 Select 使用1.1.
g3$widths[[9]] <- unit(1.1, "null")
g3$widths
# [1] 5.5points 0cm 1grobwidth
# [4] 0.691935845800368cm 2.2null 5.5points
# [7] 2.2null 5.5points 1.1null
# [10] 0cm 0cm 11points
# [13] 1.36216308454538cm 0points 5.5points
grid.draw(g3)