Ggplot2 и gridExtra: полностью удалите полосу в facet_grid - не просто невидимую - программирование
Подтвердить что ты не робот

Ggplot2 и gridExtra: полностью удалите полосу в facet_grid - не просто невидимую

У меня есть два графика, которые я размещаю один над другим, следующим образом:

library(ggplot2)
library(gridExtra)
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- p2 + facet_grid(cyl ~ .)
grid.arrange(p1, p2, ncol=1)

Для этого мне нужно, чтобы оси x верхнего и нижнего графиков выстроились в линию, однако из-за полосы влево граненный граф уже, чем верхний график. Я могу сделать полосу невидимой, используя:

theme(strip.text.y = element_blank())
theme(strip.background = element_blank())

Однако это не избавляет от пространства, которое занимает полоса. Поэтому мне либо нужен способ полностью избавиться от полосы, либо иметь возможность разделить мой граненный граф на отдельные графы, но каким-то образом использовать одну и ту же метку оси Y. На моем графике у меня есть две граненые панели, которые не очень высоки, и для них не хватает места для каждой из них имеют ось y по размеру по размеру.

Любые предложения?

4b9b3361

Ответ 1

Мое решение состояло в том, чтобы найти ширину полосы, а затем установить границы обоих графиков равными нулю, но сжимать один без полосы немного меньше (ширина полосы), чтобы они выглядели как тот же размер. По пробке и ошибке кажется, что полоса шириной около 0,5 (но, я думаю, вы могли бы понять это программно). Поэтому просто убедитесь, что правый участок на графике без текста полосы составляет 0,5 строки больше, чем у невидимой полосы:

#  Add a line of width 0.5 on the left but set all other margins to zero
p1 <- p1 + theme( plot.margin = unit( c(0,0.5,0,0) , units = "lines" ) )
#  Set all margins to zero, the strip will take up a phantom amount of invisible space
p2 <- p2 + theme(strip.text.y = element_blank() , 
  strip.background = element_blank(),
  plot.margin = unit( c(0,0,0,0) , units = "lines" ) )

grid.arrange(p1, p2, ncol=1)

Очевидно, вы можете отрегулировать поля по своему усмотрению (например, добавьте 1 к первой позиции в каждом числовом векторе в plot.margin, чтобы получить границу одной строки в верхней части каждого графика), если вы сохраняете 0,5 строки больше поля на правой границе второго участка они будут выглядеть одинаково.

enter image description here

Ответ 2

Здесь другое решение, использующее viewport и grid.layout. Я создаю 2 видовых экрана с двумя разностными макетами. Затем я размещаю графики ggplot2, используя аргумент vp.

library(grid)
pushViewport(plotViewport(c(1,1,1,1),layout = grid.layout(2, 1)))
print(p2, vp = viewport(layout.pos.row = 2, layout.pos.col = 1))
pushViewport(viewport(layout.pos.row=1,
  layout = grid.layout(1, 2,widths = unit(c(1,1),c("null",'lines')))))
print(p1, vp = viewport(layout.pos.row = 1, layout.pos.col = 1))
upViewport(2)             

enter image description here

Ответ 3

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

library(ggplot2)
library(gridExtra)
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() +
         xlab(NULL)
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() +
         facet_wrap( ~ cyl, ncol = 1)
grid.arrange(p1, p2, ncol=1)

Ответ 4

Другое решение, использующее функции из пакета gtable. Он выравнивает графики, но сохраняет текст полосы. Он использует функцию gtable, чтобы вставить столбец справа от p1, равный ширине текста полосы p2.

library(ggplot2)
library(gridExtra)
library(gtable)

p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- p2 + facet_grid(cyl ~ .)

g1 = ggplotGrob(p1)
# gtable_show_layout(g1)  # View the layout
# g1$widths               # Get the widths of g1

g2 = ggplotGrob(p2)
# gtable_show_layout(g2)  # View the layout
# g2$widths               # Check the widths of g2

#  Add new column to the right of g1 equal in width the strip width of g2.
#  In g2, strip width is the 5th element the vector g2$widths
g1 <- gtable_add_cols(g1, g2$widths[5])  
grid.arrange(g1, g2, ncol=1)

enter image description here

## But note that if the y-axis titles and/or labels take up different widths, 
#  the two plots are not aligned
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() +
   theme(axis.title.y = element_text(angle = 0, size = 30))
p2 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p2 <- p2 + facet_grid(cyl ~ .)

g1 = ggplotGrob(p1)
g2 = ggplotGrob(p2)

g1 <- gtable_add_cols(g1, g2$widths[5])  # New column added to the right
grid.arrange(g1, g2, ncol=1)             # Plots are not aligned

enter image description here

# Need to set widths to the maximums in the two plots, 
# i.e., set g2 widths to be the same as g1 widths
g2$widths <- g1$widths
grid.arrange(g1, g2, ncol=1)            # Plots are aligned

enter image description here

РЕДАКТИРОВАТЬ: Или, как предложено baptiste, используйте функцию gtable rbind():

g1 = ggplotGrob(p1)
g2 = ggplotGrob(p2)

g1 <- gtable_add_cols(g1, g2$widths[5], 4)  # New column added to the right 

library(grid)
grid.draw(rbind(g1, g2, size = "first"))