web-dev-qa-db-ja.com

ggplot2による並列プロット

ggplot2パッケージ を使用して2つのプロットを並べて配置したい、つまりpar(mfrow=c(1,2))と同じようにします。

たとえば、次の2つのプロットを同じ縮尺で並べて表示します。

x <- rnorm(100)
eps <- rnorm(100,0,.2)
qplot(x,3*x+eps)
qplot(x,2*x+eps)

それらを同じdata.frameに入れる必要がありますか?

qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
295

任意のggplotsを並べて(または、グリッド上にn個のプロット)

gridExtra パッケージの関数grid.arrange()は複数のプロットを結合します。これは、2つを並べて配置する方法です。

require(gridExtra)
plot1 <- qplot(1)
plot2 <- qplot(1)
grid.arrange(plot1, plot2, ncol=2)

これは、2つのプロットが同じデータに基づいていない場合、たとえばreshape()を使用せずに異なる変数をプロットしたい場合などに役立ちます。

これは副作用として出力をプロットします。副作用をファイルに出力するには、デバイスドライバ(pdfpngなど)を指定します。

pdf("foo.pdf")
grid.arrange(plot1, plot2)
dev.off()

または、arrangeGrob()ggsave()と組み合わせて使用​​します。

ggsave("foo.pdf", arrangeGrob(plot1, plot2))

これは、par(mfrow = c(1,2))を使用して2つの異なるプロットを作成するのと同じです。これはデータを整理する時間を節約するだけでなく、2つの異なるプロットが必要なときに必要です。


付録:ファセットの使用

ファセットは、異なるグループに対して同様のプロットを作成するのに役立ちます。これは以下の多くの答えで以下に指摘されていますが、私は上記のプロットと同等の例でこのアプローチを強調したいと思います。

mydata <- data.frame(myGroup = c('a', 'b'), myX = c(1,1))

qplot(data = mydata, 
    x = myX, 
    facets = ~myGroup)

ggplot(data = mydata) + 
    geom_bar(aes(myX)) + 
    facet_wrap(~myGroup)

更新

cowplotplot_grid関数は、grid.arrangeの代替としてチェックする価値があります。以下の@ = claus-wilkeによる answer および同等のアプローチについては このビネット を参照してください。しかし、この関数は このビネット に基づいて、プロットの位置とサイズをより細かく制御できます。

436
David LeBauer

grid.arrangeに基づくソリューションの1つの欠点は、ほとんどのジャーナルが要求するように、プロットに文字(A、Bなど)でラベルを付けることを難しくするということです。

私は cowplot パッケージを書き、この問題(そして他のいくつかの問題)、特にplot_grid()関数を解決しました。

library(cowplot)

iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
  geom_boxplot() + theme_bw()

iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
  geom_density(alpha = 0.7) + theme_bw() +
  theme(legend.position = c(0.8, 0.8))

plot_grid(iris1, iris2, labels = "AUTO")

enter image description here

plot_grid()が返すオブジェクトは別のggplot2オブジェクトであり、通常どおりggsave()を使って保存できます。

p <- plot_grid(iris1, iris2, labels = "AUTO")
ggsave("plot.pdf", p)

あるいは、カウロット関数save_plot()を使うことができます。これはggsave()のまわりの薄いラッパーで、組み合わされたプロットの正しい寸法を得るのを簡単にします。例えば:

p <- plot_grid(iris1, iris2, labels = "AUTO")
save_plot("plot.pdf", p, ncol = 2)

(引数ncol = 2は、2つのプロットが並んでいることをsave_plot()に伝え、save_plot()は保存された画像を2倍の幅にします。)

プロットをグリッドに配置する方法のより詳細な説明については、 this vignette. を参照してください。 共有の凡例を使用してプロットを作成する方法を説明するビネットもあります。 .

よくある混乱の1つのポイントは、cowplotパッケージがデフォルトのggplot2テーマを変更することです。このパッケージは、もともと社内のラボ用に書かれたものであり、デフォルトのテーマを使用しないため、このように動作します。これにより問題が発生した場合は、次の3つの方法のいずれかを使用して問題を回避できます。

1.プロットごとにテーマを手動で設定します。 上記の例で+ theme_bw()を使って行ったように、各プロットに常に特定のテーマを指定するのは良い習慣だと思います。特定のテーマを指定した場合、デフォルトのテーマは関係ありません。

2.デフォルトのテーマをggplot2のデフォルトに戻します。 これを1行のコードで実行できます。

theme_set(theme_gray())

3.パッケージを付けずにカウロット関数を呼び出します。 library(cowplot)require(cowplot)を呼び出すことはできず、代わりにcowplot::を前に付けてcowplot関数を呼び出すこともできます。たとえば、ggplot2のデフォルトテーマを使用した上記の例は、次のようになります。

## Commented out, we don't call this
# library(cowplot)

iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
  geom_boxplot()

iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
  geom_density(alpha = 0.7) +
  theme(legend.position = c(0.8, 0.8))

cowplot::plot_grid(iris1, iris2, labels = "AUTO")

enter image description here

更新:ggplot2 3.0.0から、プロットは直接ラベルを付けることができます。 here.

124
Claus Wilke

次のmultiplot関数は Winston ChangのR料理書 から使用できます。

multiplot(plot1, plot2, cols=2)

multiplot <- function(..., plotlist=NULL, cols) {
    require(grid)

    # Make a list from the ... arguments and plotlist
    plots <- c(list(...), plotlist)

    numPlots = length(plots)

    # Make the panel
    plotCols = cols                          # Number of columns of plots
    plotRows = ceiling(numPlots/plotCols) # Number of rows needed, calculated from # of cols

    # Set up the page
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(plotRows, plotCols)))
    vplayout <- function(x, y)
        viewport(layout.pos.row = x, layout.pos.col = y)

    # Make each plot, in the correct location
    for (i in 1:numPlots) {
        curRow = ceiling(i/plotCols)
        curCol = (i-1) %% plotCols + 1
        print(plots[[i]], vp = vplayout(curRow, curCol ))
    }

}
44
David LeBauer

パッチワーク パッケージを使うと、単に+演算子を使うことができます。

# install.packages("devtools")
devtools::install_github("thomasp85/patchwork")

library(ggplot2)
p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))

library(patchwork)
p1 + p2

patchwork

18
Deena

はい、データを適切に整理する必要があると思います。一つの方法はこれでしょう:

X <- data.frame(x=rep(x,2),
                y=c(3*x+eps, 2*x+eps),
                case=rep(c("first","second"), each=100))

qplot(x, y, data=X, facets = . ~ case) + geom_smooth()

私はPlyrや再構築にもっと良いトリックがあると確信しています - 私はまだHadleyによるこれらすべての強力なパッケージをスピードアップすることに実際には限界があります。

17

変形パッケージを使用すると、このようなことができます。

library(ggplot2)
wide <- data.frame(x = rnorm(100), eps = rnorm(100, 0, .2))
wide$first <- with(wide, 3 * x + eps)
wide$second <- with(wide, 2 * x + eps)
long <- melt(wide, id.vars = c("x", "eps"))
ggplot(long, aes(x = x, y = value)) + geom_smooth() + geom_point() + facet_grid(.~ variable)
15
Thierry

更新:この答えは非常に古いものです。 gridExtra::grid.arrange()が現在推奨されている方法です。それが役に立つかもしれない場合に備えて、私はこれをここに残します。


Stephen Turner さんがarrange()関数を投稿しました 遺伝学を成し遂げる ブログ (申請方法については投稿を参照)

vp.layout <- function(x, y) viewport(layout.pos.row=x, layout.pos.col=y)
arrange <- function(..., nrow=NULL, ncol=NULL, as.table=FALSE) {
 dots <- list(...)
 n <- length(dots)
 if(is.null(nrow) & is.null(ncol)) { nrow = floor(n/2) ; ncol = ceiling(n/nrow)}
 if(is.null(nrow)) { nrow = ceiling(n/ncol)}
 if(is.null(ncol)) { ncol = ceiling(n/nrow)}
        ## NOTE see n2mfrow in grDevices for possible alternative
grid.newpage()
pushViewport(viewport(layout=grid.layout(nrow,ncol) ) )
 ii.p <- 1
 for(ii.row in seq(1, nrow)){
 ii.table.row <- ii.row 
 if(as.table) {ii.table.row <- nrow - ii.table.row + 1}
  for(ii.col in seq(1, ncol)){
   ii.table <- ii.p
   if(ii.p > n) break
   print(dots[[ii.table]], vp=vp.layout(ii.table.row, ii.col))
   ii.p <- ii.p + 1
  }
 }
}
10
Jeromy Anglim

ggplot2はグリッドグラフィックに基づいており、グリッドグラフィックはページ上にプロットを配置するための異なるシステムを提供します。グリッドオブジェクト(grobsと呼ばれる)は必ずしもすぐには描画されないが、変換される前に通常のRオブジェクトとして保存され操作されるので、par(mfrow...)コマンドは直接の同等物を持たない。グラフィカルな出力に。これはこの基本グラフィックのモデルを描くよりも大きな柔軟性を可能にしますが、戦略は必然的に少し異なります。

私はgrid.arrange()にできるだけ近い単純なインターフェースを提供するためにpar(mfrow)を書きました。最も単純な形式では、コードは次のようになります。

library(ggplot2)
x <- rnorm(100)
eps <- rnorm(100,0,.2)
p1 <- qplot(x,3*x+eps)
p2 <- qplot(x,2*x+eps)

library(gridExtra)
grid.arrange(p1, p2, ncol = 2)

enter image description here

より多くのオプションは このビネット に詳述されています。

一般的な不満の1つは、プロットが必ずしも整列されていないことです。 grid.arrangeは特別な場合のggplot2オブジェクトを試みないで、それらを他の球根(例えばラティスプロット)と同じように扱います。それは単に長方形のレイアウトで球根を配置します。

Ggplot2オブジェクトの特別な場合のために、私は同様のインターフェースを持つ別の関数ggarrangeを書きました。これは(ファセットプロットを含む)プロットパネルを整列させ、ユーザー定義時に縦横比を尊重しようとします。

library(Egg)
ggarrange(p1, p2, ncol = 2)

両方の関数はggsave()と互換性があります。さまざまなオプションの概要と歴史的背景については、 このビネットで追加情報 を参照してください。

9
baptiste

言及する価値がある multipanelfigureパッケージ もあります。こちらの答え もご覧ください

library(ggplot2)
theme_set(theme_bw())

q1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
q2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
q3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec))
q4 <- ggplot(mtcars) + geom_bar(aes(carb))

library(magrittr)
library(multipanelfigure)
figure1 <- multi_panel_figure(columns = 2, rows = 2, panel_label_type = "none")
# show the layout
figure1

figure1 %<>%
  fill_panel(q1, column = 1, row = 1) %<>%
  fill_panel(q2, column = 2, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2, row = 2)
figure1

# complex layout
figure2 <- multi_panel_figure(columns = 3, rows = 3, panel_label_type = "upper-roman")
figure2

figure2 %<>%
  fill_panel(q1, column = 1:2, row = 1) %<>%
  fill_panel(q2, column = 3, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2:3, row = 2:3)
figure2

2018-07-06に リプレックスパッケージ (v0.2.0.9000)によって作成されました。

6
Tung

tidyverseを使う:

x <- rnorm(100)
eps <- rnorm(100,0,.2)
df <- data.frame(x, eps) %>% 
  mutate(p1 = 3*x+eps, p2 = 2*x+eps) %>% 
  tidyr::gather("plot", "value", 3:4) %>% 
  ggplot(aes(x = x , y = value)) + 
    geom_point() + 
    geom_smooth() + 
    facet_wrap(~plot, ncol =2)

df

enter image description here

4
aelwan

ループを使用して複数のggplotプロットをプロットしたい場合は上記の解決策は効率的ではないかもしれません(例: ループを使用して異なるY軸値を持つggplotで複数のプロットを作成する これは、未知の(または大きな)データセットを分析する際の望ましい手順です(たとえば、データセット内のすべての変数の数をプロットする場合)。

以下のコードは、上記の「multiplot()」を使用してそれを行う方法を示しています。そのソースは次のとおりです。 http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2)

plotAllCounts <- function (dt){   
  plots <- list();
  for(i in 1:ncol(dt)) {
    strX = names(dt)[i]
    print(sprintf("%i: strX = %s", i, strX))
    plots[[i]] <- ggplot(dt) + xlab(strX) +
      geom_point(aes_string(strX),stat="count")
  }

  columnsToPlot <- floor(sqrt(ncol(dt)))
  multiplot(plotlist = plots, cols = columnsToPlot)
}

1つのページにggplotを使用して印刷されたすべての変数のカウントを取得するために - 今関数を実行します

dt = ggplot2::diamonds
plotAllCounts(dt)

注意すべき点が1つあります。
aes(get(strX))の代わりにggplotを扱うときに通常ループで使用するaes_string(strX)を使用しても、希望するプロットは描画されません。代わりに、最後のプロットを何度もプロットします。私はその理由を考え出していません - aesaes_stringggplotで呼ばれる必要があるかもしれません。

そうでなければ、その機能が役に立つことを願ってください。

1
IVIM

cowplotパッケージは、出版に適した方法で、これを実行するための素晴らしい方法を提供します。

x <- rnorm(100)
eps <- rnorm(100,0,.2)
A = qplot(x,3*x+eps, geom = c("point", "smooth"))+theme_gray()
B = qplot(x,2*x+eps, geom = c("point", "smooth"))+theme_gray()
cowplot::plot_grid(A, B, labels = c("A", "B"), align = "v")

enter image description here

0
tim