完美地对齐几个图

时间:2016-07-28 13:04:49

标签: r ggplot2

我的目标是一个复合图,它结合了散点图和2个图来进行密度估算。我面临的问题是由于密度图的缺失轴标记和散点图的图例,密度图未能与散点图正确对齐。可以通过使用plot.margin播放arround来调整它。但是,这不是一个更好的解决方案,因为如果对图形进行更改,我将不得不一遍又一遍地进行调整。有没有办法以某种方式定位所有绘图,以便实际绘图面板完美对齐?

enter image description here

我尽量保持代码尽可能小,但为了重现问题,它仍然是非常多的。

library(ggplot2)
library(gridExtra)

df <- data.frame(y     = c(rnorm(50, 1, 1), rnorm(50, -1, 1)), 
                 x     = c(rnorm(50, 1, 1), rnorm(50, -1, 1)), 
                 group = factor(c(rep(0, 50), rep(1,50))))


empty <- ggplot() + 
              geom_point(aes(1,1), colour="white") +
              theme(                              
                plot.background = element_blank(), 
                panel.grid.major = element_blank(), 
                panel.grid.minor = element_blank(), 
                panel.border = element_blank(), 
                panel.background = element_blank(),
                axis.title.x = element_blank(),
                axis.title.y = element_blank(),
                axis.text.x = element_blank(),
                axis.text.y = element_blank(),
                axis.ticks = element_blank()
              )


scatter <-  ggplot(df, aes(x = x, y = y, color = group)) + 
                geom_point() +
                theme(legend.position = "bottom")

top_plot <- ggplot(df, aes(x = y)) + 
                geom_density(alpha=.5, mapping = aes(fill = group)) + 
                theme(legend.position = "none") +
                theme(axis.title.y = element_blank(),
                      axis.title.x = element_blank(),
                      axis.text.y=element_blank(),
                      axis.text.x=element_blank(),
                      axis.ticks=element_blank() )

right_plot <- ggplot(df, aes(x = x)) + 
                geom_density(alpha=.5, mapping = aes(fill = group)) + 
                coord_flip() + theme(legend.position = "none") +
                theme(axis.title.y = element_blank(),
                      axis.title.x = element_blank(),
                      axis.text.y  = element_blank(),
                      axis.text.x=element_blank(),
                      axis.ticks=element_blank())

grid.arrange(top_plot, empty, scatter, right_plot, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))

5 个答案:

答案 0 :(得分:5)

另一种选择,

library(egg) 
ggarrange(top_plot, empty, scatter, right_plot, 
          ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))

enter image description here

答案 1 :(得分:2)

以下是基础R中的解决方案。它使用this question中的line2user函数。

par(mar = c(5, 4, 6, 6))
with(df, plot(y ~ x, bty = "n", type = "n"))
with(df[df$group == 0, ], points(y ~ x, col = "dodgerblue2"))
with(df[df$group == 1, ], points(y ~ x, col = "darkorange"))

x0_den <- with(df[df$group == 0, ], 
               density(x, from = par()$usr[1], to = par()$usr[2]))
x1_den <- with(df[df$group == 1, ], 
               density(x, from = par()$usr[1], to = par()$usr[2]))
y0_den <- with(df[df$group == 0, ], 
               density(y, from = par()$usr[3], to = par()$usr[4]))
y1_den <- with(df[df$group == 1, ], 
               density(y, from = par()$usr[3], to = par()$usr[4]))

x_scale <- max(c(x0_den$y, x1_den$y))
y_scale <- max(c(y0_den$y, y1_den$y))

lines(x = x0_den$x, y = x0_den$y/x_scale*2 + line2user(1, 3), 
      col = "dodgerblue2", xpd = TRUE)
lines(x = x1_den$x, y = x1_den$y/x_scale*2 + line2user(1, 3), 
      col = "darkorange", xpd = TRUE)

lines(y = y0_den$x, x = y0_den$y/x_scale*2 + line2user(1, 4), 
      col = "dodgerblue2", xpd = TRUE)
lines(y = y1_den$x, x = y1_den$y/x_scale*2 + line2user(1, 4), 
      col = "darkorange", xpd = TRUE)

enter image description here

答案 2 :(得分:2)

这是一个使用pBase->foo()包中plot_gridcowplot包中grid.arrange组合的选项:

gridExtra

首先,一些设置:将绘图图例提取为单独的grob的函数,以及一些可重用的绘图组件:

library(ggplot2)
library(gridExtra)
library(grid)
library(cowplot)

df <- data.frame(y     = c(rnorm(50, 1, 1), rnorm(50, -1, 1)), 
                 x     = c(rnorm(50, 1, 1), rnorm(50, -1, 1)), 
                 group = factor(c(rep(0, 50), rep(1,50))))

创建图:

# Function to extract legend
# https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs
g_legend<-function(a.gplot) {
  tmp <- ggplot_gtable(ggplot_build(a.gplot))
  leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
  legend <- tmp$grobs[[leg]]
  return(legend)
  }


# Set up reusable plot components
my_thm = list(theme_bw(),
              theme(legend.position = "none",
                    axis.title.y = element_blank(),
                    axis.title.x = element_blank(),
                    axis.text.y=element_blank(),
                    axis.text.x=element_blank(),
                    axis.ticks=element_blank()))

marg = theme(plot.margin=unit(rep(0,4),"lines"))

现在列出三个情节加上传奇:

## Empty plot
empty <- ggplot() + geom_blank() + marg

## Scatterplot
scatter <-  ggplot(df, aes(x = x, y = y, color = group)) + 
  geom_point() +
  theme_bw() + marg +
  guides(colour=guide_legend(ncol=2))

# Copy legend from scatterplot as a separate grob
leg = g_legend(scatter)

# Remove legend from scatterplot
scatter = scatter + theme(legend.position = "none")

## Top density plot
top_plot <- ggplot(df, aes(x = y)) + 
  geom_density(alpha=.5, mapping = aes(fill = group)) + 
  my_thm + marg

## Right density plot
right_plot <- ggplot(df, aes(x = x)) + 
  geom_density(alpha=.5, mapping = aes(fill = group)) + 
  coord_flip() + my_thm + marg

enter image description here

答案 3 :(得分:1)

使用Align ggplot2 plots vertically的答案通过添加到gtable来对齐情节(最有可能使这一点复杂化)

library(ggplot2)
library(gtable)
library(grid)

您的数据和图表

set.seed(1)
df <- data.frame(y     = c(rnorm(50, 1, 1), rnorm(50, -1, 1)), 
                 x     = c(rnorm(50, 1, 1), rnorm(50, -1, 1)), 
                 group = factor(c(rep(0, 50), rep(1,50))))

scatter <-  ggplot(df, aes(x = x, y = y, color = group)) + 
                geom_point() +  theme(legend.position = "bottom")

top_plot <- ggplot(df, aes(x = y)) + 
                geom_density(alpha=.5, mapping = aes(fill = group))+
               theme(legend.position = "none") 

right_plot <- ggplot(df, aes(x = x)) + 
                geom_density(alpha=.5, mapping = aes(fill = group)) + 
                coord_flip() + theme(legend.position = "none") 

使用Bapistes回答的想法

g <- ggplotGrob(scatter)

g <- gtable_add_cols(g, unit(0.2,"npc"))    
g <- gtable_add_grob(g, ggplotGrob(right_plot)$grobs[[4]], t = 2, l=ncol(g), b=3, r=ncol(g))

g <- gtable_add_rows(g, unit(0.2,"npc"), 0)
g <- gtable_add_grob(g, ggplotGrob(top_plot)$grobs[[4]], t = 1, l=4, b=1, r=4)

grid.newpage()
grid.draw(g)

哪个产生

enter image description here

我使用ggplotGrob(right_plot)$grobs[[4]]手动选择panel grob,但当然可以自动执行此操作

还有其他选择:Scatterplot with marginal histograms in ggplot2

答案 4 :(得分:0)

当您将轴设置为element_blank()时,它会移除轴并允许图形填充剩余的空间。相反,设置为color =&#34; white&#34; (或者你的背景是什么):

# All other code remains the same:

scatter <-  ggplot(df, aes(x = x, y = y, color = group)) + 
  geom_point() +
  theme(legend.position = "bottom")

top_plot <- ggplot(df, aes(x = y)) + 
  geom_density(alpha=.5, mapping = aes(fill = group)) + 
  theme(legend.position = "none")+
  theme(axis.title = element_text(color = "white"),
        axis.text=element_text(color = "white"),
        axis.ticks=element_line(color = "white") )

right_plot <- ggplot(df, aes(x = x)) + 
  geom_density(alpha=.5, mapping = aes(fill = group)) + 
  coord_flip() +
  theme(legend.position = "bottom") +
  theme(axis.title = element_text(color = "white"),
        axis.text  = element_text(color = "white"),
        axis.ticks=element_line(color = "white"))

grid.arrange(top_plot, empty, scatter, right_plot, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))

existence

我还必须在正确的情节中添加一个图例。如果您不想这样做,我还建议您将散点中的图例移动到图中:

scatter <-  ggplot(df, aes(x = x, y = y, color = group)) + 
  geom_point() +
  theme(legend.position = c(0.05,0.1))

top_plot <- ggplot(df, aes(x = y)) + 
  geom_density(alpha=.5, mapping = aes(fill = group)) + 
  theme(legend.position = "none")+
  theme(axis.title = element_text(color = "white"),
        axis.text=element_text(color = "white"),
        axis.ticks=element_line(color = "white") )

right_plot <- ggplot(df, aes(x = x)) + 
  geom_density(alpha=.5, mapping = aes(fill = group)) + 
  coord_flip() +
  theme(legend.position = "none") +
  theme(axis.title = element_text(color = "white"),
        axis.text  = element_text(color = "white"),
        axis.ticks=element_line(color = "white"))

grid.arrange(top_plot, empty, scatter, right_plot, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))

enter image description here