2016-01-14 2 views
6

Поскольку я обновил ggplot2 2.0.0, я не могу организовать диаграммы с помощью gridExtra. Проблема в том, что граненые диаграммы будут сжаты, а другие будут расширяться. Ширины в основном перепутаны. Я хочу, чтобы организовать их подобно тому, как эти одиночные фасеточные участки: left align two graph edges (ggplot)Упорядочить общую ширину участка с граненым ggplot 2.0.0 и gridExtra

я поставил воспроизводимый код

library(grid) # for unit.pmax() 
library(gridExtra) 

plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) + 
    geom_point() + 
    facet_grid(. ~ Species) + 
    stat_smooth(method = "lm") 

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 # extract the first three widths, 
mpg.widths <- g.mpg$widths # same for mpg plot 
max.widths <- unit.pmax(iris.widths, mpg.widths) 

g.iris$widths <- max.widths # assign max. widths to iris gtable 
g.mpg$widths <- max.widths # assign max widths to mpg gtable 

grid.arrange(g.iris,g.mpg,ncol=1) 

enter image description here

Как вы увидите, верхний график, то первый аспект является расширяется, а остальные 2 сжимаются справа. Нижняя диаграмма не охватывает всю ширину.

Возможно ли, что новая версия ggplot2 возится с шириной gtable?

Кто-нибудь знает обходное решение?

Большое спасибо

EDIT: Добавлено изображение диаграммы

Я ищу что-то вроде:

enter image description here

+0

g.iris $ widths и g.iris $ widths - это разные длины, поэтому (я думаю) вы не можете непосредственно применять unit.pmax через них. Поэтому просто попробуйте применить его к ширине для части слева и справа от панелей. 'max.widths <- unit.pmax (iris.widths [1: 3], mpg.widths [1: 3]); g.iris $ widths [1: 3] <- max.widths; g.mpg $ widths [1: 3] <- max.widths; g.iris $ widths [9] <- unit.c (g.mpg $ widths [5] + g.mpg $ widths [6]) ' – user20650

+0

Спасибо за предложение! Я также пробовал подмножество ширины, но не работал. последняя часть кода, которую я раньше не видел, но когда я ее применяю, я получаю сообщение об ошибке из grid.arrange (и grid.draw) 'Ошибка в unit (widths, default.units): (list) объект не может быть принужден к типу «double». Я также попытался найти, что означает каждое число в ширине gtable, но мне не удалось получить эту информацию. –

+0

. Для вашего примера выше, он должен работать без ошибок - для меня (для его наилучшего способа это другое вопрос;)). Я заменил ваши три строки 'max.widths <- unit.pmax (iris.widths, mpg.widths); ; g.iris $ widths <- max.widths; g.mpg $ widths <- max.widths' с четырьмя строками в комментарии выше. – user20650

ответ

0

Снимая эти две строки и сохранить остальное, это работал просто отлично.

g.iris$widths <- max.widths # assign max. widths to iris gtable 
g.mpg$widths <- max.widths # assign max widths to mpg gtable 

enter image description here

Вероятно, это было ограничение ширины них.

+0

Спасибо за отзыв, но это всего лишь воспроизводимый случай. Мой фактический случай намного сложнее, и удаление этих строк делает диаграммы не правильно выровненными. Фактически, воспроизводимая ошибка не выводит выровненные диаграммы, если мы удалим эти строки. –

+0

. Чего вы хотите достичь? Хотите поместить все графики подряд? – ldepaula3

+1

Моя первоначальная настройка - это набор строк из 4 строк, 1 столбца, которые выровнены (1 график на строку). С ggplot2 1.0.1 это делается с помощью вышеуказанного кода, но с ggplot2 2.0.0 выдает ошибку, показанную в диаграммах, которые вы можете увидеть в моем первом сообщении. –

0

Это некрасиво, но если вы находитесь под давлением времени, этот хак будет работать (не обобщаемый и не зависящий от размера окна графика). В основном сделайте верхний участок 2 столбца с пустым графиком справа и угадайте ширину.

grid.arrange(
    grid.arrange(plot.iris, ggplot() + theme_minimal(),ncol=2, widths = c(.9, .1)), 
    plot.mpg, 
    ncol=1 
) 
1

Я не уверен, что вы все еще ищете решение, но это довольно общее. Я использую ggplot 2.1.0 (теперь на CRAN). Он основан на this solution. Я разбиваю проблему на две части. Во-первых, я рассматриваю левую часть сюжетов, следя за тем, чтобы ширина для материала оси была одинаковой. Это уже сделали другие, и на SO есть решения. Но я не думаю, что результат выглядит хорошо. Я бы предпочел, чтобы панели тоже выровнялись с правой стороны. Во-вторых, процедура гарантирует, что ширина столбцов справа от панелей одинакова. Он делает это, добавляя столбец соответствующей ширины справа от каждого из графиков. (Там же, возможно, аккуратнее способы сделать это Eсть - см. @baptiste решения.)

library(grid) # for pmax 
library(gridExtra) # to arrange the plots 
library(ggplot2) # to construct the plots 
library(gtable) # to add columns to gtables of plots without legends 

mpg$g = "Strip text" 

# Four fairly irregular plots: legends, faceting, strips 
p1 <- ggplot(mpg, aes(displ, 1000*cty)) + 
    geom_point() + 
    facet_grid(. ~ drv) + 
    stat_smooth(method = "lm") 

p2 <- ggplot(mpg, aes(x = hwy, y = cyl, colour = factor(cyl))) + 
    geom_point() + 
    theme(legend.position=c(.8,.6), 
     legend.key.size = unit(.3, "cm")) 

p3 <- ggplot(mpg, aes(displ, cty, colour = factor(drv))) + 
    geom_point() + 
    facet_grid(. ~ drv) 


p4 <- ggplot(mpg, aes(displ, cty, colour = factor(drv))) + 
    geom_point() + 
    facet_grid(g ~ .) 

# Sometimes easier to work with lists, and it generalises nicely 
plots = list(p1, p2, p3, p4) 

# Convert to gtables 
g = lapply(plots, ggplotGrob) 

# Apply the un-exported unit.list function for grid package to each plot 
g.widths = lapply(g, function(x) grid:::unit.list(x$widths)) 


## Part 1: Make sure the widths of left axis materials are the same across the plots 
# Get first three widths from each plot 
g3.widths <- lapply(g.widths, function(x) x[1:3]) 

# Get maximum widths for first three widths across the plots 
g3max.widths <- do.call(unit.pmax, g3.widths) 

# Apply the maximum widths to each plot 
for(i in 1:length(plots)) g[[i]]$widths[1:3] = g3max.widths 

# Draw it 
do.call(grid.arrange, c(g, ncol = 1)) 


## Part 2: Get the right side of the panels aligned 
# Locate the panels 
panels <- lapply(g, function(x) x$layout[grepl("panel", x$layout$name), ]) 

# Get the position of right most panel 
r.panel = lapply(panels, function(x) max(x$r)) # position of right most panel 

# Get the number of columns to the right of the panels 
n.cols = lapply(g.widths, function(x) length(x)) # right most column 

# Get the widths of these columns to the right of the panels 
r.widths <- mapply(function(x,y,z) x[(y+1):z], g.widths, r.panel, n.cols) 

# Get the sum of these widths 
sum.r.widths <- lapply(r.widths, sum) 

# Get the maximum of these widths 
r.width = do.call(unit.pmax, sum.r.widths) 

# Add a column to the right of each gtable of width 
# equal to the difference between the maximum 
# and the width of each gtable's columns to the right of the panel. 
for(i in 1:length(plots)) g[[i]] = gtable_add_cols(g[[i]], r.width - sum.r.widths[[i]], -1) 

# Draw it 
do.call(grid.arrange, c(g, ncol = 1)) 

enter image description here

+1

Я всегда задавался вопросом, почему ggplot не всегда сохраняет пустое пространство, независимо от того, существует ли там легенда или нет. Предания BTW не всегда на правой стороне, что может стать кошмаром, если вы нацелены на полную общность. – baptiste

+1

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

+0

Я подумал о трех регионах. Я еще раз подумаю, но не пару дней. Если вы хотите войти в решение, не стесняйтесь. –

5

один вариант массировать каждый участок в 3х3 gtable, где центральная клетка оборачивает весь сюжет панели.

Используя пример из @SandyMuspratt

# devtools::install_github("baptiste/egg") 
grid.draw(egg::ggarrange(plots=plots, ncol=1)) 

enter image description here

преимущество в том, что, как только в этом стандартном формате, участки могут быть объединены в различных раскладок гораздо легче, независимо от количества панелей, легенды , оси, полосы и т.д.

grid.newpage() 
grid.draw(ggarrange(plots=list(p1, p4, p2, p3), widths = c(2,1), debug=TRUE)) 

enter image description here

+0

ваш пакет яиц - это драгоценный камень! Выравнивание каждого элемента чисто потрясающее. Гранированные и незавершенные участки затем выравниваются по площади участка. И метки оси могут иметь разную длину! Сделал мой день и многие другие, чтобы прийти наверняка. Большое спасибо! – aurelien

+0

Это потрясающее решение! Мне интересно, можно ли контролировать, насколько велики разные отдельные сюжеты в «яйце»? Например, plot1 равен 1/2 размера комбинированного графика, а plot2 - 4 места в оставшейся половине. Благодаря! – Tung

+1

(предполагая, что вы говорите о последнем примере, макет 2x2), это то, что ширина (должна делать); есть ошибка, хотя IIRC, поэтому вам, возможно, придется вручную отредактировать полученные в результате ширины/высоты бит в некоторых случаях – baptiste

Смежные вопросы