ggplot2 и gridExtra: уменьшить расстояние между графиками, на которых удалены фасетные полосы.

Я хочу построить ряд плотно расположенных графиков, как показано в следующем игрушечном примере:

library(ggplot2)
library(gridExtra)
set.seed(314159)
n <- 100
data <- data.frame(x = rnorm(n), y = rnorm(n), z = rep("dummy var", n))

p00 <- ggplot(data, aes(x)) + stat_density() + theme(plot.margin = unit(c(0,0,0,0), units = "lines" ), axis.text = element_blank(), axis.title = element_blank(), axis.ticks = element_blank()) + labs(x = NULL, y = NULL)
p01 <- ggplot(data, aes(x, y)) + geom_point() + theme(plot.margin = unit(c(0,0,0,0), units = "lines" ), axis.text = element_blank(), axis.title = element_blank(), axis.ticks = element_blank()) + labs(x = NULL, y = NULL)
p10 <- ggplot(data, aes(y, x)) + geom_point() + theme(plot.margin = unit(c(0,0,0,0), units = "lines" ), axis.text = element_blank(), axis.title = element_blank(), axis.ticks = element_blank()) + labs(x = NULL, y = NULL)
p11 <- ggplot(data, aes(y)) + stat_density() + theme(plot.margin = unit(c(0,0,0,0), units = "lines" ), axis.text = element_blank(), axis.title = element_blank(), axis.ticks = element_blank()) + labs(x = NULL, y = NULL)

grid.arrange(p00, p01, p10, p11, ncol = 2)

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

p00 <- p00 + facet_grid(z ~ z)
p01 <- p01 + facet_grid(z ~ z)
p10 <- p10 + facet_grid(z ~ z)
p11 <- p11 + facet_grid(z ~ z)

grid.arrange(p00, p01, p10, p11, ncol = 2)

Затем я удаляю полоски в соответствии с процедурой, описанной в этот пост. Однако полученные графики довольно широко разнесены по сравнению:

p00 <- p00 + theme(plot.margin = unit(c(0,0.5,0.5,0), units = "lines" ), strip.background = element_blank(), strip.text = element_blank())
p01 <- p01 + theme(plot.margin = unit(c(0,0.5,0.5,0), units = "lines" ), strip.background = element_blank(), strip.text = element_blank())
p10 <- p10 + theme(plot.margin = unit(c(0,0.5,0.5,0), units = "lines" ), strip.background = element_blank(), strip.text = element_blank())
p11 <- p11 + theme(plot.margin = unit(c(0,0.5,0.5,0), units = "lines" ), strip.background = element_blank(), strip.text = element_blank())

grid.arrange(p00, p01, p10, p11, ncol = 2)

Любые предложения о том, как уменьшить расстояние между графиками, будут высоко оценены.


person Paul S    schedule 29.01.2015    source источник


Ответы (1)


Чтобы удалить все элементы, связанные с осями, в дополнение к элементам, для которых вы установили значение element_blank, поля делений и длину делений необходимо установить равными нулю. Но останется место для фасонных планок. Установка фона и текста на element_blank не влияет на высоту и ширину полос. Чтобы удалить полоски, я использую функции, которые манипулируют макетом gtable. Тем не менее, я думаю, что между сюжетами лучше оставлять пустое пространство. Я установил небольшое поле сюжета на 0,2 строки.

library(ggplot2)
library(gridExtra)
set.seed(314159)
n <- 100
data <- data.frame(x = rnorm(n), y = rnorm(n), z1 = rep("dummy var", n), z2 = rep("dummy var", n))

theme = theme(plot.margin = unit(c(.2,.2,.2,.2), units = "lines"), 
         axis.text = element_blank(), 
         axis.title = element_blank(), 
         axis.ticks = element_blank(), 
         axis.ticks.length = unit(0, "lines"))
labs = labs(x = NULL, y = NULL) 

p00 <- ggplot(data, aes(x)) + stat_density() + theme + labs + facet_grid(z1 ~ z2)
p01 <- ggplot(data, aes(x, y)) + geom_point() + theme + labs + facet_grid(z1 ~ z2)
p10 <- ggplot(data, aes(y, x)) + geom_point() + theme + labs + facet_grid(z1 ~ z2)
p11 <- ggplot(data, aes(y)) + stat_density() + theme + labs + facet_grid(z1 ~ z2)

Здесь манипулируют макетом gtable.

# Get the four gtables (and the four plots) into a list
pList = list(p00, p01, p10, p11)
gList = lapply(pList, ggplotGrob)

# Remove the top strip from each plot
stripT <- subset(gList[[1]]$layout, grepl("strip-t", gList[[1]]$layout$name))
gList = lapply(gList, function(x) x[-stripT$t, ])

# Remove the right strip from each plot
stripR <- subset(gList[[1]]$layout, grepl("strip-r", gList[[1]]$layout$name))
gList = lapply(gList, function(x) x[, -stripR$r])

# Draw the revised plots
nCol <- floor(sqrt(length(pList)))
do.call(grid.arrange, c(gList, ncol = nCol))

введите здесь описание изображения

Редактировать: использование измененных данных и графика.

library(grid)

data <- data.frame(x = rnorm(n), y = rnorm(n), z = rep("dummy var", n), u = seq(1, n) %% 2) 
p01 <- ggplot(data, aes(x, y)) + geom_point() + theme + labs + facet_grid(z ~ u)

g = ggplotGrob(p01)
stripT = subset(g$layout, grepl("strip-t", g$layout$name))
g = g[-stripT$t, ]
stripR = subset(g$layout, grepl("strip-r", g$layout$name))
g = g[, -stripR$r]

grid.draw(g) # Still got the space between the facets

g$widths  # where is the space? it's the 5.55 pt width

g$widths[[5]] = unit(0, "lines") # remove it completely
g$width
grid.draw(g)
person Sandy Muspratt    schedule 30.01.2015
comment
Большое спасибо! Это отлично работает для примера с игрушкой. Я заметил, что вертикальные полосы остаются в более общем случае, когда у нас есть: data <- data.frame(x = rnorm(n), y = rnorm(n), z = rep("dummy var", n), u = seq(1, n) %% 2) и p01 <- ggplot(data, aes(x, y)) + geom_point() + theme + labs + facet_grid(z ~ u), а все остальное такое же, как в вашем решении. Мои первоначальные попытки заставить его работать, изменив ваш код, закончились неудачей, но я опубликую ответ, если он заработает. - person Paul S; 30.01.2015
comment
Да, в ваших пересмотренных данных и графике есть встроенное пространство между двумя гранями. См. редактирование, чтобы удалить это пространство. - person Sandy Muspratt; 30.01.2015