установите для графиков ggplot одинаковую ширину по оси x и одинаковое расстояние между строками точечного графика

Обновленный вопрос для включения частичного решения, на которое уже дан ответ в SO

Я использую ggplot2 для создания нескольких графиков и gridExtra для объединения графиков в одну фигуру с несколькими панелями, все в один столбец. Моя проблема в том, что я не могу сделать так, чтобы расстояние между строками точечного графика было одинаковым на обоих графиках.

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

library(ggplot2)
# data
  dat1 <- data.frame(VARIABLES=c("Item 1", "Item 2 is a little longer"),
                     est=c(.3, .5),
                     min=c(.2, .4),
                     max=c(.4, .7))
  dat2 <- data.frame(VARIABLES=c("Item 3", 
                                 "Item 4 is even longer if you can believe it",
                                 "And there is a third item",
                                 "And a fourth item"),
                     est=c(.3, .5, .3, .5),
                     min=c(.2, .4, .2, .4),
                     max=c(.4, .7, .4, .7))
  dat <- c("dat1", "dat2")
  labs <- c("Plot 1", "Plot2")
# create plots
  count <- 1
  for (i in dat) {
    p <- ggplot(get(i), aes(x=reorder(as.character(VARIABLES), est), 
                              y=est)) +
    geom_pointrange(aes(ymin=min,
                        ymax=max),
                    linetype="dashed") +
    geom_point(size=3) +
    ylim(-1,1) +
    theme_bw() +
    labs(title = labs[count]) +
    theme(legend.position="none") +
    coord_flip()
    assign(paste(i, "plot", sep="."), p)
    count <- count+1
  }
# combine plots
  library(gridExtra)
  # approach suggested by @baptise
  # http://stackoverflow.com/questions/13294952/left-align-two-graph-edges-ggplot
  gA <- ggplotGrob(dat1.plot)
  gB <- ggplotGrob(dat2.plot)
  maxWidth = grid::unit.pmax(gA$widths[2:5], gB$widths[2:5])
  gA$widths[2:5] <- as.list(maxWidth)
  gB$widths[2:5] <- as.list(maxWidth)
  grid.arrange(gA, gB, ncol=1)

person Eric Green    schedule 26.05.2014    source источник
comment
Я собирался предложить использовать facets вместо grid.arrange, но ggplot2 в настоящее время не поддерживает свободные шкалы с недекартовой координатой или coord_flip.   -  person shadow    schedule 26.05.2014
comment
@shadow, да, я был разочарован, узнав об этом. Первоначально я думал, что грани могут быть ответом.   -  person Eric Green    schedule 26.05.2014
comment
Я думаю, что № 1 в основном является вариантом еще один вопрос   -  person baptiste    schedule 26.05.2014
comment
@baptiste, что уместно в этом случае, поскольку на (1) был дан ответ в другом вопросе, но не на (2)? Должен ли я отредактировать вопрос, чтобы включить другой ответ для (1) и уточнить, что мой вопрос касается (2)?   -  person Eric Green    schedule 26.05.2014
comment
Я понятия не имею. Я предполагаю, что лучше иметь только одну конкретную проблему для каждого вопроса. Продолжайте редактировать, я удалил свой заключительный голос.   -  person baptiste    schedule 26.05.2014
comment
Я получил «ответ» на вопрос выше, чтобы работать на меня, когда я использовал gA$widths[2:5] <- maxWidth вместо gA$widths[2:5] <- as.list(maxWidth) и т. д.   -  person André C. Andersen    schedule 27.08.2016


Ответы (3)


library(gridExtra)
library(grid)

gb1 <- ggplot_build(dat1.plot)
gb2 <- ggplot_build(dat2.plot)

# work out how many y breaks for each plot
n1 <- length(gb1$layout$panel_params[[1]]$y.labels)
n2 <- length(gb2$layout$panel_params[[1]]$y.labels)

gA <- ggplot_gtable(gb1)
gB <- ggplot_gtable(gb2)

g <- rbind(gA, gB)

# locate the panels in the gtable layout
panels <- g$layout$t[grepl("panel", g$layout$name)]
# assign new (relative) heights to the panels, based on the number of breaks
g$heights[panels] <- unit(c(n1,n2),"null")

grid.newpage()
grid.draw(g)

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

person baptiste    schedule 26.05.2014
comment
похоже, это сработает. благодаря. однако я получаю g <- gtable:::rbind_gtable(gA, gB, gC, gD, gE, "last") в своем фактическом коде (обратите внимание, я добавляю еще 3 графика) и получаю сообщение об ошибке о неиспользуемых аргументах. Я посмотрел документацию rbind.gtable, но ничего не бросилось мне в глаза. любые предположения относительно того, что вызывает ошибку? - person Eric Green; 27.05.2014
comment
Кроме того, @baptiste, можно ли изменить код, чтобы указать определенное пространство между строками? ваш код, кажется, отлично отвечает на вопрос. просто интересно, можно ли указать определенный интервал, который можно было бы применить ко всем графикам. - person Eric Green; 27.05.2014
comment
Я обновил мой первоначальный ответ, чтобы учесть несколько графиков. Расстояние между графиками определяется границами графика; в качестве альтернативы вы можете посмотреть ?gtable_add_rows и подобные функции в документации gtable. - person baptiste; 27.05.2014
comment
Я принял этот ответ, потому что он выполняет свою работу. Спасибо! Ваш другой код отлично работает для нескольких графиков, хотя я не знал, как его изменить, чтобы включить корректировку высоты, которую вы включаете в текущий ответ. Примечание для других людей, заходящих в эту ветку: длинные метки обрезаются. - person Eric Green; 27.05.2014
comment
Мне удалось заставить код в ответе отлично работать для нескольких графиков, добавив параметры для трех дополнительных графиков: gb3...gb5, n3...n5, gC...gE и g1 <- gtable:::rbind_gtable(gA, gB, "last"), g2 <- gtable:::rbind_gtable(g1, gC, "last"),...g <- gtable:::rbind_gtable(g3, gE, "last"). Мне также пришлось обновиться с помощью unit(n3,"null")...unit(n5,"null"). Наконец, установив размер вывода с помощью cairo_pdf(f, width=7, height=9) and wrapping this around grid.draw(g)` с dev.off(), мы получили великолепно выглядящую фигуру. Спасибо, @baptiste. - person Eric Green; 27.05.2014
comment
@EricGreen У вас есть код для нескольких графиков? - person BioMan; 17.07.2015
comment
@baptiste, есть ли шанс, что вы могли бы обновить это до последней версии gridExtra? возникли проблемы с тем, чтобы заставить это работать на основе github.com/baptiste/gridextra/wiki/arranging- ggplot - person Dominik; 03.03.2016
comment
Я не знаю, но я думаю, что сегодня изменился следующий синтаксис: n1 ‹- длина(gb1$layout$panel_params[[1]]$y.labels) на n1 ‹- длина(gb1$layout$panel_ranges[[1 ]]$y.метки) - person JulioSergio; 28.03.2018
comment
Вместо g ‹- rbind(gA, gB) следует использовать g ‹- gtable:::rbind_gtable(gA, gB, last) - person JulioSergio; 28.03.2018

Вот один из подходов: заполните дополнительные пробелы для более коротких меток и используйте моноширинный шрифт.

longest_name <- max(nchar(as.character(dat1$VARIABLES)), nchar(as.character(dat2$VARIABLES)))
fill_in_spaces <- function(v) paste0(paste0(rep(" ", longest_name - nchar(v)), collapse=""), v)
levels(dat1$VARIABLES) <- sapply(levels(dat1$VARIABLES), fill_in_spaces)
levels(dat2$VARIABLES) <- sapply(levels(dat2$VARIABLES), fill_in_spaces)

Далее процедура построения почти такая же, просто добавьте

p <- p + theme(text=element_text(family="Courier", size=14))

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

Есть небольшая проблема: уровни переупорядочены, поэтому пункт 3 теперь последний, но это можно легко исправить, как описано, например. здесь.

person tonytonov    schedule 26.05.2014
comment
интересный подход к проблеме №2, @tonytonov - person Eric Green; 26.05.2014
comment
@EricGreen Спасибо, это была совершенно случайная идея, и она (на удивление) сработала. - person tonytonov; 26.05.2014

dat1$Plot <- "Plot 1"
dat2$Plot <- "Plot 2"
dataset <- rbind(dat1, dat2)

ggplot(
  dataset, 
  aes(
    y = reorder(as.character(VARIABLES), est), 
    x = est,
    xmin = min,
    xmax = max
  )) +
  geom_errorbarh() + geom_point() + 
facet_wrap(~Plot, ncol = 1, scales = "free_y")

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

person Thierry    schedule 26.05.2014
comment
facet_grid(Plot~., scales = "free", space="free") решит #1 - person baptiste; 26.05.2014