2016-07-28 46 views
5

我的目標是將散點圖和2個地塊組合爲密度估計值的複合圖。我面臨的問題是由於密度圖的缺失軸標記和散點圖的圖例,密度圖與散點圖沒有正確對齊。它可以通過與plot.margin圍繞進行調整。但是,這不是一個可取的解決方案,因爲如果對圖進行更改,我將不得不一遍又一遍地調整它。有沒有辦法以一種方式定位所有的地塊,以便實際的繪圖板完美對齊?完美對齊幾塊地塊

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)) 
+0

僅供參考,您應該'set.seed()',你中的R示例,使輸出重複性 – Chris

+0

@克里斯例子之前:實際數據在這裏並不重要。所以我認爲這並不重要。 – Alex

+1

http://stackoverflow.com/questions/17370853/align-ggplot2-plots-vertically/17371177#17371177 – user20650

回答

1

Align ggplot2 plots vertically使用答案對準情節:如果你不希望這樣,我也建議也正在傳說中的分散是劇情內(最有可能使這個複雜化!)

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

+0

我真的很喜歡'gtable'。不幸的是,我不明白它的概念。有沒有一個很好的解釋它的工作方式?我找不到任何有用的東西。 – Alex

+0

其記錄不佳。我可以通過玩這個網站上的問題和答案來使用它(很少)。 Baptiste已經在他的wiki上寫了一下https://github.com/baptiste/gridextra/wiki/gtable – user20650

+0

在這種情況下,它可能是新文檔功能的一個很好的候選人。 – Alex

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

+0

謝謝,但我想堅持'ggplot2'。 – Alex

+0

這裏ggplot的需求是什麼? – dayne

+0

我用我所有的地塊ggplot,我也很好奇它如何可以用ggplot完成。 – Alex

0

當您將軸設置爲element_blank(),它消除了軸,並允許圖形,以填補空間的其餘部分。相反,設爲COLOR =「白色」(或任何你的背景):

# 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)) 

enter image description here

我也有一個傳說添加到右側的情節。通過向gtable

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

+0

這與我想要的更接近,但我希望圖例處於該位置,如果散點圖在y軸上有標籤,則它仍不能在左側正確對齊。 – Alex

2

下面是使用從gridExtracowplot包和grid.arrangeplot_grid組合的選項:

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)))) 

首先,一些設置:函數提取圖例作爲一個單獨的GROB,再加上一對夫婦可重用組件的情節的:

# 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 

現在鋪陳三個地塊,加上傳說:

# Lay out the three plots 
p1 = plot_grid(top_plot, empty, scatter, right_plot, align="hv", 
       rel_widths=c(3,1), rel_heights=c(1,3)) 

# Combine plot layout and legend 
grid.arrange(p1, leg, heights=c(10,1)) 

enter image description here

+0

謝謝!這也是我很好的解決方案,但在這種情況下我更喜歡gtable。 – Alex

4

另一種選擇,

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