Установка ширины в объекте gtable сворачивает график; раньше это работало, но больше не работает.

Следующий код раньше работал, но больше не работает. Кто-нибудь знает, что происходит? Это должно быть какое-то изменение в базовом коде gtable.

require(cowplot) # for plot_grid()
require(grid) # for unit_max()

# make two plots
plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) + 
  geom_point() + facet_grid(. ~ Species) + stat_smooth(method = "lm") +
  background_grid(major = 'y', minor = "none") + 
  panel_border()
plot.mpg <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) + 
  geom_point(size=2.5)

g.iris <- ggplotGrob(plot.iris) # convert to gtable
g.mpg <- ggplotGrob(plot.mpg) # convert to gtable

iris.widths <- g.iris$widths[1:3] # extract the first three widths, 
                                  # corresponding to left margin, y lab, and y axis
mpg.widths <- g.mpg$widths[1:3] # same for mpg plot
max.widths <- unit.pmax(iris.widths, mpg.widths) # calculate maximum widths
g.iris$widths[1:3] <- max.widths # assign max. widths to iris gtable
g.mpg$widths[1:3] <- max.widths # assign max widths to mpg gtable

plot_grid(g.iris, g.mpg, labels = "AUTO", ncol = 1)

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

Это должно выглядеть так (с идеально выровненными линиями оси Y по вертикали): введите здесь описание изображения

Ошибка, кажется, происходит в этой строке:

g.iris$widths[1:3] <- max.widths

Любое понимание будет оценено.

Обратите внимание, что подобные решения использовались в течение длительного времени, см., например. здесь. И функция plot_grid() в cowplot использует подобный код также для выравнивания графиков, и он все еще работает. Так что это меня полностью озадачило.


person Claus Wilke    schedule 06.03.2016    source источник


Ответы (1)


Изменить
В grid версии 3.3.0 это больше не проблема. То есть строки кода, содержащие grid:::unit.list() ниже, можно удалить.

Проблема заключается в том, как устанавливаются единицы измерения. Посмотрите на g.iris$widths. Вы заметите, что цифры есть, но единицы измерения пропущены. См. этот вопрос и ответ и этот. После преобразования графиков в gtables вам потребуется: g.iris$widths = grid:::unit.list(g.iris$widths)

require(grid) # for unit_max()
require(cowplot)

# make two plots
plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) + 
  geom_point() + facet_grid(. ~ Species) + stat_smooth(method = "lm") + 
  background_grid(major = 'y', minor = "none") + 
  panel_border()
plot.mpg <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) + 
  geom_point(size=2.5) 

g.iris <- ggplotGrob(plot.iris) # convert to gtable   
g.mpg <- ggplotGrob(plot.mpg) # convert to gtable

g.iris$widths = grid:::unit.list(g.iris$widths)   
g.mpg$widths =  grid:::unit.list(g.mpg$widths)

iris.widths <- g.iris$widths[1:3] # extract the first three widths, 
                                  # corresponding to left margin, y lab, and y axis
mpg.widths <- g.mpg$widths[1:3] # same for mpg plot

max.widths <- unit.pmax(iris.widths, mpg.widths) # calculate maximum widths

g.iris$widths[1:3] <- max.widths # assign max. widths to iris gtable
g.mpg$widths[1:3] <- max.widths # assign max widths to mpg gtable

plot_grid(g.iris, g.mpg, labels = "AUTO", ncol = 1)
person Sandy Muspratt    schedule 06.03.2016
comment
действительно, grid:::unit.list() был нужен в течение некоторого времени; Я забыл, когда я начал замечать поломку с ggplot2. Эта неэкспортированная функция сетки стала почти обязательным требованием для такого выравнивания графиков, что может быть проблематичным в пакете. - person baptiste; 06.03.2016
comment
Большое спасибо! Проблема с осевыми линиями — это ошибка в последней версии ggplot2 2.1.0. Это уже исправлено на github, ожидается отправка в CRAN. - person Claus Wilke; 06.03.2016
comment
Я удалил ссылки на осевые линии. - person Sandy Muspratt; 06.03.2016
comment
Чтобы было ясно: ошибка линии оси есть в ggplot2 2.1.0. Я исправил cowplot, чтобы обойти ошибку, и отправил его в CRAN. - person Claus Wilke; 06.03.2016
comment
@baptiste У вас есть идеи, что можно сделать, чтобы grid:::unit.list() стала экспортируемой функцией? Если это так важно, оно должно быть доступно. На самом деле, я подумывал о написании дополнительных вспомогательных функций для выполнения подобных манипуляций, но не знаю, что делать дальше. - person Claus Wilke; 06.03.2016
comment
мое личное мнение в настоящее время состоит в том, чтобы поместить копию этой функции в мой собственный пакет (на самом деле я могу это сделать). К счастью, в этом конкретном случае нет ничего низкоуровневого/внутреннего, поэтому этого может быть достаточно. Вы также можете попытать счастья, напомнив разработчикам grid (/gtable/ggplot2) об этой проблеме. - person baptiste; 06.03.2016
comment
@baptiste С последней разрабатываемой версией R этот пример теперь должен работать без grid:::unit.list(): stat.ethz.ch/pipermail/r-devel/2016-March/072434.html - person Claus Wilke; 08.03.2016
comment
@ClausWilke Спасибо, что отследили это. - person Sandy Muspratt; 08.03.2016