結合されたggplotsに共通の凡例を追加する


138

2つのggplotsがあり、これをと水平方向に揃えますgrid.arrange。私はたくさんのフォーラム投稿を調べてきましたが、私が試したものはすべて、更新されて別の名前が付けられたコマンドのようです。

私のデータは次のようになります。

# Data plot 1                                   
        axis1     axis2   
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.417117 -0.002592
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.186860 -0.203273

# Data plot 2   
        axis1     axis2
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988

#And I run this:
library(ggplot2)
library(gridExtra)


groups=c('group1','group2','group3','group4','group1','group2','group3','group4')

x1=data1[,1]
y1=data1[,2]

x2=data2[,1]
y2=data2[,2]

p1=ggplot(data1, aes(x=x1, y=y1,colour=groups)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

p2=ggplot(data2, aes(x=x2, y=y2,colour=groups)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

#Combine plots
p3=grid.arrange(
p1 + theme(legend.position="none"), p2+ theme(legend.position="none"), nrow=1, widths = unit(c(10.,10), "cm"), heights = unit(rep(8, 1), "cm")))

これらのプロットから凡例をどのように抽出し、組み合わせたプロットの下部/中央に追加しますか?


2
私は時々この問題を抱えています。プロットをファセットしたくない場合は、凡例を付けて保存するのが最も簡単な解決策です。Photoshop/ Ilustratorを使用して、空白の凡例プロットに貼り付けます。エレガントではありませんが、実用的で迅速かつ簡単です。
Stephen Henderson

@StephenHendersonそれが答えです。ファセットまたはgfxエディターによる後処理。
Brandon Bertelsen、2012年

回答:


107

2015年2月の更新

以下のスティーブンの答えを見てください


df1 <- read.table(text="group   x     y   
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.417117 -0.002592
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.186860 -0.203273",header=TRUE)

df2 <- read.table(text="group   x     y   
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988",header=TRUE)


library(ggplot2)
library(gridExtra)

p1 <- ggplot(df1, aes(x=x, y=y,colour=group)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8) + theme(legend.position="bottom")

p2 <- ggplot(df2, aes(x=x, y=y,colour=group)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

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

mylegend<-g_legend(p1)

p3 <- grid.arrange(arrangeGrob(p1 + theme(legend.position="none"),
                         p2 + theme(legend.position="none"),
                         nrow=1),
             mylegend, nrow=2,heights=c(10, 1))

これが結果のプロットです: 共通の凡例を持つ2つのプロット


2
どちらの回答も、新しいバージョンのggplot2がコードを壊したときに更新できる同じWikiページを指します。
バプティスト2016年

6年以上後、この答えは私の問題を解決しました。ありがとう!
SPK.z

これは一部または大部分の人にとっては簡単なことかもしれませんが、すぐには理解できなかったので、コメントしたいと思いました。(下ではなく)プロットの上に共通の凡例が必要な場合は、引数を切り替えるだけで済みます。上記の例では、mylegendはの前にありarrangeGrob()ます。また、高さを逆にする必要があります(つまりheights=c(1,10)
ljh2001

113

また、使用することggarrangeをからggpubrパッケージとセット「common.legend = TRUE」:

library(ggpubr)

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
p1 <- qplot(carat, price, data = dsamp, colour = clarity)
p2 <- qplot(cut, price, data = dsamp, colour = clarity)
p3 <- qplot(color, price, data = dsamp, colour = clarity)
p4 <- qplot(depth, price, data = dsamp, colour = clarity) 

ggarrange(p1, p2, p3, p4, ncol=2, nrow=2, common.legend = TRUE, legend="bottom")

ここに画像の説明を入力してください


1
renderPlot()で光沢のあるアプリケーション(またはflexdashboard)内でこれが機能しない可能性はありますか?通常のプロットを持つ通常のRスクリプトで完全に正常に動作します。しかし、flexdashboardでrenderPlot()を使用して作成したプロットでまったく同じことを行うと、何も表示されません。
Tingolfin

1
これをありがとう-私はこれが私が探していたものに対して断然最も簡単な解決策だったと思います
コマルラーティ

これはすごい!ありがとうございました!
ヤンヌ

@Tingolfin 他の関数でプロットする必要があるときにprint(ggarrangeobject)ggarrangeオブジェクトの1つをラップしなければならないことがありましたrenderPlot()
ブランドン

common.legend = TRUE私が必要なのはこれだけです!
Aryo

62

ローランドの答えは更新が必要です。参照:https : //github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs

このメソッドは、ggplot2 v1.0.0用に更新されました。

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


grid_arrange_shared_legend <- function(...) {
    plots <- list(...)
    g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))$grobs
    legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
    lheight <- sum(legend$height)
    grid.arrange(
        do.call(arrangeGrob, lapply(plots, function(x)
            x + theme(legend.position="none"))),
        legend,
        ncol = 1,
        heights = unit.c(unit(1, "npc") - lheight, lheight))
}

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
p1 <- qplot(carat, price, data=dsamp, colour=clarity)
p2 <- qplot(cut, price, data=dsamp, colour=clarity)
p3 <- qplot(color, price, data=dsamp, colour=clarity)
p4 <- qplot(depth, price, data=dsamp, colour=clarity)
grid_arrange_shared_legend(p1, p2, p3, p4)

欠如を注意してくださいggplot_gtableggplot_buildggplotGrob代わりに使用されます。この例は、上記のソリューションより少し複雑ですが、それでも解決されました。


10
こんにちは、私は6つのプロットを持っています。6つのプロットを2行3列に配置し、上部に凡例を描画したいので、関数を変更するにはどうすればよいgrid_arrange_shared_legendですか。ありがとうございました!
just_rookie

4
@just_rookie関数を変更して、ncolとnrowの配置だけでなく、異なる配置を使用できるようにする方法を見つけましたncol = 1か?
ジュゼッペ

こんにちは、私はこの解決策を試しましたが、うまくいきますが、印刷すると、1ページではなく2 PDFページが表示されます。おかげで
HanniBaL90 2017年

誰がどのように私と同じISSEを得るために、ここでの回避策は次のとおりです。stackoverflow.com/questions/12481267/...
HanniBaL90

1
ここで素晴らしいもの。すべてのプロットに単一のタイトルを追加する方法はありますか?
Pertinax 2018年

27

新しい魅力的なソリューションはを使用することpatchworkです。構文は非常に簡単です:

library(ggplot2)
library(patchwork)

p1 <- ggplot(df1, aes(x = x, y = y, colour = group)) + 
  geom_point(position = position_jitter(w = 0.04, h = 0.02), size = 1.8)
p2 <- ggplot(df2, aes(x = x, y = y, colour = group)) + 
  geom_point(position = position_jitter(w = 0.04, h = 0.02), size = 1.8)

combined <- p1 + p2 & theme(legend.position = "bottom")
combined + plot_layout(guides = "collect")

reprexパッケージ(v0.2.1)によって2019-12-13に作成されました


2
:あなたは少しのコマンドの順序を変更する場合は、1行でこれを行うことができます combined <- p1 + p2 + plot_layout(guides = "collect") & theme(legend.position = "bottom")
mlcyo

17

カウプロットを使用することをお勧めします。彼らのRビネットから:

# load cowplot
library(cowplot)

# down-sampled diamonds data set
dsamp <- diamonds[sample(nrow(diamonds), 1000), ]

# Make three plots.
# We set left and right margins to 0 to remove unnecessary spacing in the
# final plot arrangement.
p1 <- qplot(carat, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt"))
p2 <- qplot(depth, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt")) + ylab("")
p3 <- qplot(color, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt")) + ylab("")

# arrange the three plots in a single row
prow <- plot_grid( p1 + theme(legend.position="none"),
           p2 + theme(legend.position="none"),
           p3 + theme(legend.position="none"),
           align = 'vh',
           labels = c("A", "B", "C"),
           hjust = -1,
           nrow = 1
           )

# extract the legend from one of the plots
# (clearly the whole thing only makes sense if all plots
# have the same legend, so we can arbitrarily pick one.)
legend_b <- get_legend(p1 + theme(legend.position="bottom"))

# add the legend underneath the row we made earlier. Give it 10% of the height
# of one plot (via rel_heights).
p <- plot_grid( prow, legend_b, ncol = 1, rel_heights = c(1, .2))
p

凡例が下部にある組み合わせプロット


これは唯一の方法であり、それにより、legend_b()を使用して、を使用してプロットに手動の凡例を配置することが可能になりましたannotate_figure(ggarrange())どうもありがとう、神のご加護を!
Jean Karlos

12

@Giuseppe、プロット配置の柔軟な仕様のためにこれを考慮する必要があるかもしれません(ここから変更されます):

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

grid_arrange_shared_legend <- function(..., nrow = 1, ncol = length(list(...)), position = c("bottom", "right")) {

  plots <- list(...)
  position <- match.arg(position)
  g <- ggplotGrob(plots[[1]] + theme(legend.position = position))$grobs
  legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
  lheight <- sum(legend$height)
  lwidth <- sum(legend$width)
  gl <- lapply(plots, function(x) x + theme(legend.position = "none"))
  gl <- c(gl, nrow = nrow, ncol = ncol)

  combined <- switch(position,
                     "bottom" = arrangeGrob(do.call(arrangeGrob, gl),
                                            legend,
                                            ncol = 1,
                                            heights = unit.c(unit(1, "npc") - lheight, lheight)),
                     "right" = arrangeGrob(do.call(arrangeGrob, gl),
                                           legend,
                                           ncol = 2,
                                           widths = unit.c(unit(1, "npc") - lwidth, lwidth)))
  grid.newpage()
  grid.draw(combined)

}

追加の引数nrowncol配置されたプロットのレイアウトを制御します。

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
p1 <- qplot(carat, price, data = dsamp, colour = clarity)
p2 <- qplot(cut, price, data = dsamp, colour = clarity)
p3 <- qplot(color, price, data = dsamp, colour = clarity)
p4 <- qplot(depth, price, data = dsamp, colour = clarity)
grid_arrange_shared_legend(p1, p2, p3, p4, nrow = 1, ncol = 4)
grid_arrange_shared_legend(p1, p2, p3, p4, nrow = 2, ncol = 2)

ここに画像の説明を入力してください ここに画像の説明を入力してください


他のソリューションと同じように、試してみましたが、うまくいきましたが、印刷すると、1ページではなく2 PDFページが表示されました。おかげで
HanniBaL90 2017年

誰がどのように私と同じISSEを得るために、ここでの回避策は次のとおりです。stackoverflow.com/questions/12481267/...
HanniBaL90

誰かが私に解決策を説明できますか?凡例を下ではなく上に配置するにはどうすればよいですか?おかげで
HanniBaL90

8

両方のプロットで同じ変数をプロットする場合、最も簡単な方法は、データフレームを1つに結合してから、facet_wrapを使用することです。

あなたの例のために:

big_df <- rbind(df1,df2)

big_df <- data.frame(big_df,Df = rep(c("df1","df2"),
times=c(nrow(df1),nrow(df2))))

ggplot(big_df,aes(x=x, y=y,colour=group)) 
+ geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8) 
+ facet_wrap(~Df)

プロット1

diamondsデータセットを使用した別の例。これは、プロット間で共通の変数が1つしかない場合でも機能させることができることを示しています。

diamonds_reshaped <- data.frame(price = diamonds$price,
independent.variable = c(diamonds$carat,diamonds$cut,diamonds$color,diamonds$depth),
Clarity = rep(diamonds$clarity,times=4),
Variable.name = rep(c("Carat","Cut","Color","Depth"),each=nrow(diamonds)))

ggplot(diamonds_reshaped,aes(independent.variable,price,colour=Clarity)) + 
geom_point(size=2) + facet_wrap(~Variable.name,scales="free_x") + 
xlab("")

プロット2

2番目の例でトリッキーなことは、すべてを1つのデータフレームに結合すると、因子変数が数値に強制変換されることです。したがって、理想的には、主に、関心のあるすべての変数が同じ型である場合にこれを実行します。


1

@ギセップ:

私はグロブなどについてはまったく知りませんが、2つのプロットのソリューションをハッキングしました。任意の数に拡張できるはずですが、セクシーな関数ではありません。

plots <- list(p1, p2)
g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))$grobs
legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
lheight <- sum(legend$height)
tmp <- arrangeGrob(p1 + theme(legend.position = "none"), p2 + theme(legend.position = "none"), layout_matrix = matrix(c(1, 2), nrow = 1))
grid.arrange(tmp, legend, ncol = 1, heights = unit.c(unit(1, "npc") - lheight, lheight))

1

凡例が両方のプロットで同じである場合、を使用する簡単な解決策がありgrid.arrangeます(凡例を両方のプロットに垂直または水平に揃えたい場合)。一番下または一番右のプロットの凡例を保持し、もう一方の凡例は省略します。ただし、凡例を1つのプロットだけに追加すると、1つのプロットのサイズが他のプロットに対して相対的に変更されます。これを回避するには、heightsコマンドを使用して手動で調整し、同じサイズに保ちます。を使用grid.arrangeして、共通の軸タイトルを作成することもできます。これにはlibrary(grid)に加えて必要になることに注意してくださいlibrary(gridExtra)。垂直プロットの場合:

y_title <- expression(paste(italic("E. coli"), " (CFU/100mL)"))

grid.arrange(arrangeGrob(p1, theme(legend.position="none"), ncol=1), arrangeGrob(p2, theme(legend.position="bottom"), ncol=1), heights=c(1,1.2), left=textGrob(y_title, rot=90, gp=gpar(fontsize=20)))

以下は、私が取り組んでいるプロジェクトの同様のグラフの結果です。 ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.