Rで複数のプロットを並べる

R
Published

November 1, 2024

Rではデフォルトではに1回のプロットで1つのグラフしか作れませんが、設定を変更することで複数のプロットを並べることができます。 やり方は3通りあります。

  1. par(mfrow)par(mfcol)を設定する
  2. layout関数で設定する
  3. splot.screenで設定する

それぞれについてまとめていきます。

parの使用

parはグラフィックパラメータの指定に使います。 つまり、parametersの略ということになります。 par(mfcol= c(行数, 列数))もしくはpar(mfrow= c(行数, 列数))とすることで、何個のプロットをどのように配置するかを決めることができます。

mfcolは列から、mfrowは行からプロットを作成します。 まずはmfcolから挙動を確認してみます。

1par(mfcol = c(2,2))
2plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "3")
plot(1, 1, pch = "4")
1
2行2列のプロットをから作成します
2
4つのプロットを作成します

次にmfrowを確認してみます。

1par(mfrow = c(2,2))
2plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "3")
plot(1, 1, pch = "4")
1
2行2列のプロットをから作成します
2
4つのプロットを作成します

設定の戻し方

parで指定したパラメータはデバイスが閉じられるまで永続します。プロットのあとにdev.offもしくは変更前のparを保存しておいてあとから戻すことでリセットできます。

設定を戻さずプロットを重ねた場合はparの設定が引き継がれます。

par(mfrow = c(2,2))
plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "3")
plot(1, 1, pch = "4")

plot(1,1, pch = "5")

5個目のプロットが左上に表示されていることがわかります。

dev.off

dev.offはデバイス(プロット)を終了させる関数です。

par(mfrow = c(2,2))
plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "3")
plot(1, 1, pch = "4")

dev.off()
null device 
          1 
plot(1, 1, pch = "5")

一度dev.offを挟むことにより、1つのプロットだけがプロット領域全体に表示されるようになります。

parを使ってもとに戻す

次は、変更前のparを変数に入れておき、あとからもとに戻す方法です。

old_par <- par()
par(mfrow = c(2,2))
plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "3")
plot(1, 1, pch = "4")

par(old_par)
Warning in par(old_par): graphical parameter "cin" cannot be set
Warning in par(old_par): graphical parameter "cra" cannot be set
Warning in par(old_par): graphical parameter "csi" cannot be set
Warning in par(old_par): graphical parameter "cxy" cannot be set
Warning in par(old_par): graphical parameter "din" cannot be set
Warning in par(old_par): graphical parameter "page" cannot be set
plot(1, 1, pch = "5")

old_parに一度parを保存し、あとからそれで上書きしています。 警告が表示されることがありますが、多くの場合は問題ありません。 複数のグラフィックパラメータを変更した際などに役に立ちます。

layout関数の使用

layout関数はプロット領域を柔軟に割り当てることができる関数です。 layout(行列)と指定することで、引数の行列の通りプロットを割り当て、行列の数字の順番にプロットします。

まずはレイアウトに用いる行列を作成してみます。

layout_matrix <- matrix(1:4, ncol = 2)
print(layout_matrix)
     [,1] [,2]
[1,]    1    3
[2,]    2    4

2行2列で列から数字が割り振られています。

次にlayout関数でこの行列のとおりにプロットします。

layout(layout_matrix)
plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "4")
plot(1, 1, pch = "3")

ちなみに、行からプロットを埋めたい場合には、matrix関数の引数にbyrow = TRUEを指定します。

layout_matrix <- matrix(1:4, ncol = 2, byrow = TRUE)
print(layout_matrix)
     [,1] [,2]
[1,]    1    2
[2,]    3    4
layout(layout_matrix)
plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "3")
plot(1, 1, pch = "4")

layout関数の便利な点は、行列内の任意の場所にプロットを割り当てられることです。 作成したい領域のとおりに行列の数字を割り振ります。 ここでは2行2列で、1列目に1を2つ並べ、2列目に2, 3と割り当てます。

layout_matrix <- matrix(c(1, 1, 2, 3), ncol = 2)
print(layout_matrix)
     [,1] [,2]
[1,]    1    2
[2,]    1    3

3つのプロットを並べてみます。

layout(layout_matrix)
plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "3")

行列の数字のとおり、1列目に2スペース分を使用して縦長のプロットを作成することができました。

このように、柔軟かつわかりやすくプロット領域を作成できるのがlayout関数の強みと言えます。

設定の戻し方

layoutの場合、元に戻すにはlayout(1)とします。 これは、1行1列の行列を指定しており、つまりプロット領域に1つのプロットを配置することになります。

layout(layout_matrix)
plot(1, 1, pch = "1")
plot(1, 1, pch = "2")
plot(1, 1, pch = "3")

layout(1)
plot(1, 1, pch = "4")

split.screenの使用

こちらは挙動が少しややこしいです。 具体例で確認してみます。

1split.screen(c(2, 1))
2split.screen(c(1, 3), screen = 2)
3screen(1)
plot(1, 1, pch = "1")
4screen(4)
plot(1, 1, pch = "4")
1
プロット領域を2行1列、つまり上下2分割にします。このとき、上がscreen = 1, 下がscreen = 2になります
2
下のscreen = 2を1行3列に3分割します。左側からそれぞれscreen = 3, 4, 5と当てはめられます
3
screen = 1にプロットを作成します
4
screen = 4にプロットを作成します。このとき、2行目のプロット領域は左から3, 4, 5と番号が振られていることに注意します

[1] 1 2
[1] 3 4 5

ちなみにこのときにscreen(2)と指定すると、split.screen(c(1, 3), screen = 2)が無視され、2行1列のプロットが作成されます。

split.screen(c(2, 1))
split.screen(c(1, 3), screen = 2)
screen(1)
plot(1, 1, pch = "1")
1screen(2)
plot(1, 1, pch = "2")
1
2行目のスクリーンにプロットを作成します

[1] 6 7
[1]  8  9 10

つまり、split.screenを使用するとスクリーンが上書きされるということがわかります。

まとめ

コードの書きやすさ、わかりやすさはpar > layout > split.screenだと思いますが、柔軟性はその逆であるように思います。

個人的には、サクッと複数のグラフを並べたいときはpar、あるグラフを大きくしたいときはlayoutのように使い分けている気がします。最近はlayoutをよく使っています。 実はsplit.screenは使ったことはありません。

Back to top