2014-09-17 3 views
2

Я пытаюсь создать схему из трех диаграмм рассеяния с общими осями и краевыми гистограммами. Кажется, это должно быть просто, но это дает мне возможность. Я пробовал подходы с gridExtra и gtable, оба из которых получили общую схему, как я хочу, но с выравниваниями и размерами графика, которые были отключены.Как организовать участки с общими осями?

Есть много других сообщений, связанных с этим вопросом, и я экспериментировал с ответами на многие из них, особенно ответы @baptiste here и here. Подход последнего к управлению шириной может быть ключом к выравниванию, но я не понял его достаточно хорошо, чтобы адаптировать его к моей проблеме.

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

  • Нижний правый участок больше, чем два других. Это была проблема со всеми подходами, включая grid.arrange(), с помощью которых я поместил пустой прямоугольник grob, чтобы сбалансировать графики рассеяния.
  • Размеры марганцовых гистограмм уходят, а не то, что я ожидаю от кода, а именно, что их узкое измерение будет примерно на 1/4 размера ширины разброса.
  • Интервал участков слишком широк.
  • Ни одна из маргинальных гистограмм не выравнивается правильно с графиками рассеяния.
  • Маргинальная гистограмма справа (c) настолько узка, что она вообще не отображается в png, но она появляется (хотя и слишком узкая) в средстве просмотра графики RStudio, хотя только при «увеличении» ».

Бонусные баллы за ответ, который правильно выравнивает оси графиков, даже если ширина меток осей варьируется между графиками, поскольку они будут гораздо более адаптированы для будущих проблем.

multiplot

library(ggplot2) 
library(grid) 
library(gtable) 
data <- data.frame(a = rnorm(100, 30, 3), b = rnorm(100, 40, 5), c=rnorm(100, 50, 3)) 
b_a.scatter <- ggplot(data, aes(x=a, y=b)) + geom_point() + coord_equal(ratio=1, xlim=c(0,100), ylim=c(0,100)) + 
    theme(
    axis.text.x = element_blank(), 
    axis.title.x = element_blank(), 
    axis.ticks.x = element_blank(), 
    plot.margin = unit(c(1,0,-0.5,1), "cm") 
) 

c_a.scatter <- ggplot(data, aes(x=a, y=c)) + geom_point() + coord_equal(ratio=1, xlim=c(0,100), ylim=c(0,100)) + 
    theme(plot.margin = unit(c(-0.5,0,0.5,1), "cm")) 

c_b.scatter <- ggplot(data, aes(x=b, y=c)) + geom_point() + coord_equal(ratio=1, xlim=c(0,100), ylim=c(0,100)) + 
    theme(
    axis.text.y = element_blank(), 
    axis.title.y = element_blank(), 
    axis.ticks.y = element_blank(), 
    plot.margin = unit(c(-0.5,0,0.5,0), "cm") 
) 

a.hist <- ggplot(data, aes(x=a)) + geom_histogram() + coord_equal(xlim=c(0,100), ratio=1/4) + 
    theme(
    axis.text.x = element_blank(), 
    axis.title.x = element_blank(), 
    axis.ticks.x = element_blank(), 
    axis.text.y = element_blank(), 
    axis.title.y = element_blank(), 
    axis.ticks.y = element_blank(), 
    plot.margin = unit(c(0,0,1,1), "cm") 
) 

b.hist <- ggplot(data, aes(x=b)) + geom_histogram() + coord_equal(xlim=c(0,100), ratio=1/4) + 
    theme(
    axis.text.x = element_blank(), 
    axis.title.x = element_blank(), 
    axis.ticks.x = element_blank(), 
    axis.text.y = element_blank(), 
    axis.title.y = element_blank(), 
    axis.ticks.y = element_blank(), 
    plot.margin = unit(c(0,0,1,0), "cm") 
) 

c.hist <- ggplot(data, aes(x=c)) + geom_histogram() + coord_flip(xlim=c(0,100)) + 
    theme(
    axis.text.x = element_blank(), 
    axis.title.x = element_blank(), 
    axis.ticks.x = element_blank(), 
    plot.margin = unit(c(0,1,0,0), "cm") 
) 

blankPanel <- grid.rect(gp=gpar(col="white")) 

gt <- gtable(widths = unit(rep(1,9), "null"), 
      heights = unit(rep(1,9), "null"), 
      respect=T) 
gl <- list(ggplotGrob(b_a.scatter), 
      ggplotGrob(c_a.scatter), ggplotGrob(c_b.scatter), ggplotGrob(c.hist), 
      ggplotGrob(a.hist), ggplotGrob(b.hist)) 

gt <- gtable_add_grob(gt, gl, 
       l=c(1,1,5,9,1,5), 
       r=c(4,4,8,9,4,8), 
       t=c(1,5,5,5,9,9), 
       b=c(4,8,8,8,9,9)) 

grid.newpage() 
png('multiplot.png') 
grid.draw(gt) 
dev.off() 

ответ

2

Вот один подход: объединить столбец диаграммы по столбцам с помощью rbind, затем cbind три столбца. Для пустых ячеек предусмотрены заглушки для манекена, они содержат только информацию о макете.

library(ggplot2) 
library(gtable) 
d <- data.frame(a = rnorm(100, 30, 3), 
       b = rnorm(100, 40, 5), 
       c=rnorm(100, 50, 3)) 

theme_set(theme_bw() + 
      theme(plot.background=element_rect(colour="red",size = 2))) 
## define simpler plots 
a <- ggplot(d, aes(x=a, y=b)) + geom_point() + xlim(0,100)+ ylim(0,90) 
b <- ggplot(d, aes(x=a, y=c)) + geom_point() + xlim(0,100) + ylim(0,90) 
c <- ggplot(d, aes(x=b, y=c)) + geom_point() + xlim(0,100) + ylim(0,90) 
ah <- ggplot(d, aes(x=a)) + geom_histogram() + 
    xlim(0,100)+ ylim(0,2000000) 
bh <- ggplot(d, aes(x=b)) + geom_histogram() + 
    xlim(0,100) + ylim(0,2000000) 
ch <- ggplot(d, aes(x=c)) + geom_histogram() + 
    coord_flip(xlim=c(0,200000)) 

pl <- lapply(list(a,b,c,ah,bh,ch), ggplotGrob) 

## function to create a dummy table (no grobs, zero size) of the right dim for (r/c)bind 
dummy_gtable <- function(g){ 
    gtable(widths=unit(rep(0,ncol(g)), 'null'), heights=unit(rep(0, nrow(g)), 'null')) 
} 

left <- rbind(pl[[1]],pl[[2]],pl[[4]]) 
middle <- rbind(dummy_gtable(pl[[1]]),pl[[3]],pl[[5]]) 
right <- rbind(dummy_gtable(pl[[1]]),pl[[6]], dummy_gtable(pl[[5]])) 
grid.newpage() 
grid.draw(cbind(left, middle, right)) 

Обратите внимание, что я использую cbind и rbind из my experimental fork of gtable, потому что выпущена версия не использует unit.pmax для сравнения Единица измерения для ширины и высоты. Пользовательские функции могут быть заимствованы у another question, чтобы использовать стабильную версию gtable.

enter image description here

+0

Там, как представляется, проблема с 'dummy_gtable()' функции, как 'влево <- rbind_gtable_max (...)' работает отлично, но 'средний <- rbind_table_max (dummy_gtable (...)) 'возвращается. 'Ошибка: is.unit (widths) не TRUE'. Обратите внимание, что я заменяю функции rbind_gtable_max и cbind_gtable_max, которые вы определили [здесь] (http://stackoverflow.com/questions/13294952/left-align-two-graph-edges-ggplot/13295880#13295880) для rbind и cbind функции в вашем решении выше. – Gregory

+0

, вероятно, из-за [этого запроса на растяжение] (https://github.com/kohske/gtable/commit/ff79f2f1c04f33951075bffc415d064080082b4c), который я объединил в своей вилке, но все еще ожидаю в официальном выпуске gtable. Попробуйте новый код. – baptiste