R

トップページ
Google
WWWを検索
サイト内を検索

前世紀、1990年代のやり方ですが、グラフィカル・オプションと低水準描画関数に習熟しておけば、ggplot2パッケージが無くてもそこそこ見やすいグラフが描けます。

1 縦横サイズを指定したウィンドウを作る

以下のようにdev.newで縦横の物理サイズを指定したウィンドウを開くことができます。

dev.new(width = 1024, height = 768, unit = "px")

空ウィンドウが開いたら、plotなどを呼び出せばそこに描画できます。

ファイルやプリンターに出力するときはもちろん、統合開発環境内のウィンドウやブラウザーに描画する場合は縦横サイズが有効にならないので注意してください。

2 縦横サイズを指定したキャンバスを作る

plotbarplotcurvehistなどの高水準描画関数はグラフィックスデバイスのオープンもやってくれますが、高水準描画関数に上手くあてはまらない場合は、低水準描画関数を組み合わせて作図することになり、まずはキャンバスを作る必要があります。

以下の例では、(0, 0)から(2, 3)までの座標を取るプロット先のキャンバスを作ります。

plot.new()
xlim <- c(0, 2)
ylim <- c(0, 3)
plot.window(xlim=xlim, ylim=ylim)

論理的な座標であって、物理的な座標では無いので、アスペクト比は縦横サイズに比例しません。

なお、Rの高水準描画関数はdemo("graphics")で見られるものの他、assocplot, cdplot, dotchart, filled.contour, fourfoldplot, mosaicplot, persp, smoothScatter, spineplot, stars, stem, stripchart, sunflowerplotと多様にあるので、低水準描画関数を組み合わせる前に、既にあるもので間に合うかも知れません。ヘルプのサンプルコードをコピペしたら、見栄えを確認できます。またggplot2のようなパッケージをインストールすれば、手軽に見栄えのよいプロットが可能です。

3 プロットする系列を増やす

plotのあとに用いるのが通例ですが、plotなしでもキャンバスを作ったあとであれば、低水準関数で描き込んでいけます。

3.1 点で増やす

やや変則的に点の代わりに文字を使うpointsの例です。詳しいオプションは後述します。

points(x, y, pch = letters[1:length(x)])

3.2 線で増やす

linesの詳しいオプションは後述します。

lines(x, y)

3.3 矢印で増やす

矢印は図中に注釈を入れるときに使うことが多いと思いますが、縦横軸とは別に時間的順序があるときは、矢印でプロットするのも手です。

arrows(x[-length(x)], y[-length(y)], x[-1], y[-1])

4 描画関数のオプション

ヘルプに大きく書いてあれば助かるのですが、探すのが大変なパラメーターの値です。

4.1 点キャラクター(pch

pointslinesで指定できるpchパラメーターは以下の値を取れます。pch=21からpch=25では内側に色がつき、引数bgで指定できます。

上述の数値指定以外もでき、pch="."とすると一点で、その他の文字を指定(e.g. pch="p")すると指定した文字でプロットします。

4.2 線種(lty

linesarrowsで指定できるltyパラメーターは以下の値をとれます。

4.3 矢印の向き(code)と鏃の角度(angle

説明のために矢印を描くときはarrowsを使いますが、線の始点(x0, y0)と終点(x1, y1)やじりをつけるかいなか、鏃の角度や長さをどうするか指定できます。

デフォルトはcode = 2です。code = 0に意味がないように思われるかも知れませんが、linesと座標の指定方法が異なるので、有用なときもあります。

4.4 プロットのタイプ(type

点だけ、線だけ、点と線の組み合わせるなどのプロットの種類を指定するtypeパラメーターは、"p", "l", "o", "b", "c", "n", "h", "s", "S"の値を取れます。

以下はpch=21で描画した例です。

"h", "s", "S"はそんなに知られていないかも知れません。 type="h"は、実質的に棒グラフになります。

type="s"は、区間(x x+1)y(x)になるグラフで、例えばx=0y=0x=1y=0.64のとき、x=0.5y=0になります。 x+1のときはxの値とx+1の値が垂直な線で結ばれ、下図ではx=1のとき、(1, 0.00)(1, 0.64)が結ばれています。

type="S"は、区間(x x+1)y(x+1)になるグラフで、例えばx=0y=0x=1y=0.64のとき、x=0.5y=0.64になります。 x+1のときはx+1の値とx+2の値が垂直な線で結ばれ、下図ではx=1のとき、(1, 0.64)(1, 0.98)が結ばれています。

4.5 色(col,bg

グラフィックス関数の引数colbgには、colors関数でリストされる色の名前を指定するか、rgb関数の戻り値を指定することができます。

colors関数は戻り値の数が多いので、以下のようにgrepで絞って選びましょう。

grep("^red[0-9]*$", colors(), value=TRUE)
[1] "red"  "red1" "red2" "red3" "red4"

今までrgbを使う機会が無かったのですが、"brown"などと同様に入れられます。

par(mar=c(4, 4, 0, 0))
curve(dgamma(x, 2), 0, 10, lwd=10, col=rgb(0.5, 0.5, 0))

4.5.1 グラデーション

rainbow関数でグラデーションが得られるわけですが、実践的にはcolorRampPalette関数でグラデーション作成関数を作ることになると思います。

crp <- colorRampPalette(c("red", "darkred"))
crp(10)
 [1] "#FF0000" "#F20000" "#E50000" "#D80000" "#CB0000" "#BE0000" "#B10000"
 [8] "#A40000" "#970000" "#8B0000"

4.6 フォントサイズ

個々の描画関数でcexなどの引数を用いて相対サイズを指摘できますが、parで一括指定することもできます。

オプション 説明
cex プロット領域全体の相対サイズ
cex.main タイトルの相対サイズ
cex.sub サブタイトルの相対サイズ
cex.lab x軸/y軸ラベルの相対サイズ
cex.axis 軸目盛りの相対サイズ

なおbarplotなど高水準関数は、cex.namesなど独自のフォントサイズ指定の引数を持ちます。

5 余白の調整

Rのプロットはデフォルトでは余白が多いです。しかし、TeXの方でタイトルや注釈を入れる場合は、プロット領域を大きく取りたくなるので、この余白を削りたくなります。 par関数のmarmgpオプションで余白を調整できるので覚えておきましょう。

5.1 marオプション

marオプションは、下・左・上・右の余白を指定します。

par(mar=c(5, 4, 4, 2) + 0.1)

5.2 mgpオプション

mgpオプションは軸ラベル・軸メモリ・軸線の位置を指定します。

par(mgp=c(3, 1, 0))

6 グラフ中文字列の上下左右の寄せ

text関数でプロット領域に文字を書き込むことができるわけですが、指定座標と文字位置の関係を示すadjパラメーターの意味を整理してみましょう。 キャンバスの中心に表示座標をとり、adjの値を色々と変えてみた結果が以下です。

  • c(1, 0)だと、文字列の右下に表示座標が来ます。
  • c(0, 0)だと、文字列の左下に表示座標が来ます。
  • c(0, 1)だと、文字列の左上に表示座標が来ます。
  • c(1, 1)だと、文字列の右上に表示座標が来ます。
  • 0.5を入れておくと中央にあわせになります。

つまり、adj=c(x, y)の値はtext関数の第1引数と第2引数が示す座標を左下においたマイナス方向への相対座標で、xは文字列の長さを単位にしており、yは文字列の高さを単位にしています。

mtext関数のadjはベクトルではなく、値一つのスカラー値になるので注意してください。上下寄せを指定できません。

7 調整に必要な情報の取得

par()$usrでプロット可能な座標の範囲を取得できます。par()$usr[1]が横軸の最小値、par()$usr[2]が横軸の最大値、par()$usr[3]が縦軸の最小値、par()$usr[4]が縦軸の最大値です。 strwidth関数で表示したときの文字列の長さ、strheight関数で高さを取得することができます。

8 数式の書き込み

表現式オブジェクトで表される数式をplotmain,xlab,ylablegendtextなどに代入し、プロットすることができます。

例えば、

text((par()$usr[1] + par()$usr[2])/2, 
    (par()$usr[3] + par()$usr[4])/2, 
    expression(f(x) == 
        frac(1, sqrt(2*pi*sigma^2))*
            exp(-frac((x - mu)^2, 2*sigma^2))), 
    cex=1.5)

とすると、以下のように中央に表示されます。

文字と数式を組み合わせるときはpasteを使います。例えばexpression(paste("quadratic equation: ", x^2+2*x*y+y^2))とすると、

となります。

タプル(座標)を書くときはexpression(group("(", list(x, y), ")"))のようにします。

利用できる記号などは、?plotmathで出せるヘルプか、demo(plotmath)で見られる例を参照してください。

9 見栄えの良い軸のつけ方

以下のプロットの軸の見栄えをよくしてみましょう。

9.1 軸の目盛りを設定する

axes=FALSEオプションをつけてplotを行い、axis関数で軸を書きます。

at <- seq(-2.5, 2.5, 0.5)
labels <- sprintf("%.2f", at)
axis(1, at=at, labels=labels)
axis(2, at=seq(0, 0.6, 0.1))

9.2 軸の目盛りを回転する

縦軸の目盛りの数字が読みづらいのでlas=1を指定して回転させます。横軸のラベルが長くて、目盛りが表示できないときなどにも有効です。

at <- seq(-2.5, 2.5, 0.5)
labels <- sprintf("%.2f", at)
axis(1, at=at, labels=labels)
axis(2, at=seq(0, 0.6, 0.1), las=1)

9.2.1 目盛りの45°回転

axis関数のlabels引数をFALSEにして、text関数に引数xpd=TRUE, srt=-45をつけてラベルを書けば、位置あわせが煩雑ですが、実現できます。

axis(1, at=at, labels=FALSE)
text(x=at + 0.15, par("usr")[3] - 0.1, labels=labels, srt=-45, adj=c(1, 1), xpd=TRUE)
axis(2, at=seq(ylim[1], ylim[2], 0.1), las=1)

9.3 縦軸のラベル位置を、縦軸の上にする

スペースの都合などで縦軸のラベル位置を動かしたいときは、plotの引数にylab=""をつけたあと、text関数に引数xpd=TRUEをつけてラベルを描きます。

表示位置はpar()$usrでとれるキャバスのサイズの左上のさらに1行上にしますが、text関数の引数にxpd=TRUEが無いと、表示可能エリア外になって表示されないので注意してください。

text(par()$usr[1], par()$usr[4], "density", adj=c(0.5, -1), xpd=TRUE)

9.4 縦軸と縦軸の位置を詰める

例にしているヒストグラムでは不要だと思いますが、axis関数の引数posで表示位置を詰めることもできます。

at <- seq(-2.5, 2.5, 0.5)
labels <- sprintf("%.2f", at)
axis(1, at=at, labels=labels, pos=0)
axis(2, at=seq(0, 0.6, 0.1), las=1, pos=at[1])
text(at[1], par()$usr[4], "density", adj=c(0.5, -1), xpd=TRUE)

10 凡例を書く

プロット後、legend("topright", "折れ線", lty=1)と言う風に凡例を書くことができますが、必然的にplinespointsにつけたパラメーターを統合した上に、見栄えを工夫すると凡例ボックスの枠線の色や太さといったパラメーターも入ってくるので、長くなります。試行錯誤する場合は、リストにまとめてdo.callするなりしましょう。

よく指定しそうなパラメーターをつけた例が以下です。

# 描画領域を作成する
par(mar=c(0, 0, 0, 0), bg="white")
plot.new()
xlim <- c(0, 1)
ylim <- c(0, 1)
plot.window(xlim=xlim, ylim=ylim)

params <- list(
    # 凡例の位置を指定
    "topleft", 
    # 凡例の描画域の隅からのマージン
    inset = 0.0,
    # 凡例のテキスト
    legend = c("point", "line", "type=\"b\"", "fill"), 
    # ポイントの形状,NAはポイントなし
    pch = c(21, NA, 22, NA),
    # 線の形状,NAは線なし
    lty = c(NA, 4, 1, NA),
    # 線の長さ
    seg.len = 3,
    # 線/ポイントの太さ
    lwd = c(3, 3, 3, NA),
    # 線/ポイントの色
    col = c("black", "red", "darkgreen", NA),
    # ポイントがpch=21~25のときの内側の色
    # "transparent"を入れておくと、type="o"に見える
    pt.bg = c("gray", NA, "green", NA),
    # 塗りつぶし色,NAは塗りつぶしなし
    fill = c(NA, NA, NA, "cyan3"),
    # 塗りつぶし領域の境界線の色
    border = c(NA, NA, NA, "blue"),
    # 塗りつぶし領域の斜線の密度(0~100),0は塗りつぶしなし
    density = c(0, 0, 0, 20),
    # 塗りつぶし領域の斜線の角度
    angle = c(NA, NA, NA, 60),
    # ポイント,線,塗りつぶし領域の大きさ
    cex = c(1.5, 1.5, 1.5, 1.5),
    # シンボル(i.e. 線/ポイント/塗りつぶし)とテキストの距離
    x.intersp = 1,
    # 凡例内の行間
    y.intersp = 1.25,
    # テキストの配置
    adj = c(0, 0.5), 
    # テキストの色
    text.col = c("black", "red", "darkgreen", "blue"),
    # 凡例の表題
    title = "凡例",
    # 凡例のシンボルとテキストを横並びにするか
    horiz = FALSE,
    # 縦並びのときは{ncol}段組みにできる
    ncol = 1, 
    # bty="n"のときは、bg, box.*は無視される
    # fillを使うときのbgはtransparentを推奨
    bty="o", bg = "transparent", box.col = "black", box.lwd=10)

do.call("legend", params)

params[[1]] <- "topright"
params[["ncol"]] <- 2
params[["inset"]] <- 0.04
params[["bty"]] <- "n"
do.call("legend", params)

params[[1]] <- "bottomright"
params[["horiz"]] <- TRUE
params[["ncol"]] = NULL 
params[["inset"]] <- 0.01
params[["bty"]] <- "o"
params[["cex"]] <- 1.125 # 全部まとめて指定もできる
do.call("legend", params)

凡例のグラフ内位置を"bottom", "bottomleft", "left", "top", "right", "center"insetで指定するのではなく、座標で指定することもできます。また、plot = FALSEで描画せずにサイズだけ戻してくれるので、やろうと思えば細かく調整も可能です。

ヘルプも充実しているのですが、ややこしいので試行錯誤して試した方がよいです。なお、シンボルのレイアウトを中央寄せにできず、density指定時の背景色を指定できないなど、fillの扱いが悪いです。プロットや折れ線が大事で、棒グラフはオマケ感が。

11 出典と注釈を書く

mtext関数を使って、プロットエリア外に出典や注釈と言った情報を書くことができます。

par(mar=c(6, 4, 0.5, 0.5))
plot(runif(15), runif(15), xlab="x", ylab="y")
baseline <- par()$mgp[1]
mtext("注意) xもyも一様分布から生成", side=1, line=baseline+1, adj=0)
mtext("出展) 特になし", side=1, line=baseline+2, adj=0)

  • 表現式をテキストにとれるので、数式の表示もできます。
  • side1のときは下側、2のときは左側、3のときは上側、4のときは右側に書けますが、だいたい1を指定することになると思います。
  • adj0が左寄せ、1が右寄せになります。上下の指定はできません。
  • lineは文の高さを基準にしたプロットが入るユーザー領域から距離で、軸ラベルなどと被らないように指定します。情報が入りきらないときは、cexでサイズを小さくするか、atでユーザー領域の座標で左に詰めるなどします。

12 グラフを見やすくする

デフォルトだと視認性が低いことが多いので、目的にあわせて装飾しましょう。

12.1 参照線を描く

ablineで垂直もしくは水平線を描くことができ、grid関数でまとめて描画できます。

par(mar=c(5, 4, 2, 2))
curve(sin(x), -pi, pi)
abline(v=0.5, lty=4, lwd=2, col="pink") # 垂直線
abline(h=0.5, lty=5, lwd=2, col="pink") # 水平線
grid() # デフォルトでは目盛の位置

gridは引数nxnyで、横方向と縦方向の線の数を指定でき、NULLだと目盛りの位置、NAだと表示なしになります。また、対数スケールのときはequilogs = FALSEをつけておかないと、目盛の位置にあわせてくれません。

12.2 領域に色を塗る

polygon関数で色を塗ります。閉路を指定しないといけないので、やや煩雑です。

# 内側を塗った後に外側(plot)を描くので低水準描画関数のみを使う
par(mar=c(3, 3, 2, 2))
plot.new()
xlim <- c(0, 3)
ylim <- c(0, 1)
plot.window(xlim=xlim, ylim=ylim)

# 閉路をつくる
n <- 100
x <- c(seq(xlim[1], xlim[2], length.out=n), xlim[2], xlim[1])
y <- c(dexp(x[1:n]), 0, 0)

# 内側を塗る
polygon(x, y, density=50, col="gray", border=NA)

# 外側の線を描く
lines(x[1:n], y[1:n], lty=1, lwd=2, col="black")

# 縦軸と横軸を描く
at <- seq(xlim[1], xlim[2], length.out=10)
axis(1, at=at, labels=sprintf("%.2f", at))
at <- seq(ylim[1], ylim[2], length.out=11)
axis(2, at=at, labels=sprintf("%.2f", at), las=1)
text(par()$usr[1], par()$usr[4], "f(x)", 
    adj=c(0.5, 0), xpd=TRUE, cex=1.25)
text(par()$usr[2], par()$usr[3], "x", 
    adj=c(0, 0.5), xpd=TRUE, cex=1.25)

# 確率密度関数を書く
text((par()$usr[1] + par()$usr[2])/2, 
    (par()$usr[3] + par()$usr[4])/2, 
    expression(f(x) == lambda*exp(-lambda*x)), 
    cex=2, adj=c(0, 0.5))

12.3 参照線や塗りつぶしをプロットの背景に描く

参照線や塗りつぶしがプロットした線や点を見えづらくしてしまう場合は、plotpanel.first引数に表現式を与えることで、参照線や塗りつぶしを簡単に先に描画できます。

par(mar=c(5, 4, 1, 1), mfrow = c(1, 2))

# プロットした線が太すぎる垂直線に隠れる
curve(sin(x), -pi, pi)
abline(v=0, lty=1, lwd=100, col="pink")

# 太すぎる垂直線の上に線がプロットされる
curve(sin(x), -pi, pi, panel.first = {
    abline(v=0, lty=1, lwd=100, col="pink")
})

12.4 ビットマップを貼り付ける

プロットにビットマップを貼り付けることもできます。

plot.new()
xlim <- c(0, 1)
ylim <- c(0, 1)
plot.window(xlim=xlim, ylim=ylim)

# 行列をラスターにして描画
invader.m <- matrix(c(0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0,
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1,
1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0), 11, 9)
invader.r <- as.raster(ifelse(1==t(invader.m), "red", "transparent"))
# interpolate=TRUE(デフォルト)の場合はアンチエイリアスがかかる
rasterImage(invader.r, 0.0, 0.6, 0.0 + 0.4, 0.6 + 0.4, interpolate=FALSE)

# PNG画像を読み込むパッケージ
library(png)

# ローカルのPNG画像をラスターにして描画
img <- readPNG(system.file("img", "Rlogo.png", package="png"))
rasterImage(as.raster(img), 0.5, 0.2, 1.0, 0.7)

# ウェブのPNG画像をラスターにして描画(readPNGがhttp://を読まない)
is <- file("http://wh.anlyznews.com/img/R.png", "rb")
raw <- readBin(is, "raw", 1024*128)
close(is)
rasterImage(as.raster(readPNG(raw)), 0.0, 0.0, 0.4, 0.4)

jpegパッケージのreadJPEG関数を使えば、JPEG画像も扱えます。

13 日本語フォント

手っ取り早く日本語を扱う方法を記します。

13.1 ラスター(ビットマップ)/Windows Meta File

MS-Windowsでラスター(ビットマップ)かWindows Meta Fileを出力をする場合は、以下のようにフォントを登録してpar時にfamily引数を指定すると、とりあえず文字化けすることは回避できます。

windowsFonts(Meiryo = windowsFont("Meiryo"))
par(family="Meiryo")

13.1.1 Linux

コマンドfc-list - familyでリストされるフォントファミリー名を(宣言なしに)画面表示とラスター画像保存に利用できます。~/.fonts/(もしくは/usr/local/share/fonts/などのroot管理領域)にフォントファイルを置いて、fc-cache -fvとすれば、リストに追加できます。

13.2 Encapsulated PostScript

epsに出力する場合は、Ghostscriptをインストールした上で、以下のGhostscriptに標準で搭載されていて、names(postscriptFonts())で確認できる、既にRに登録されたFont family名の中から、日本語フォントを選んで指定しましょう。 標準ではJapan1, Japan1HeiMin, Japan1GothicBBB, Japan1Ryuminが選択肢になります。

例えば、プロットを画面に出力した後で、

dev.copy(postscript, file = "plot.eps", width=8, height=4, family="Japan1")
dev.off()
# フォントを埋め込む.標準ではフォントを埋め込まず,gsがインストールされていない環境では文字化けしうる.
embedFonts("plot.eps",
    outfile="plot-fonts-embedded.eps",
    options="-c \"<</NeverEmbed []>> setdistillerparams\" -f ")

と言う風に指定します。

13.3 EPSで扱えるフォントを増やす

例えばTTFMeiryoを扱いたい場合は、Ghostscriptの設定ファイルのcidfmap1に、

/Meiryo            << /FileType /TrueType  /CSI [(Japan1) 6]  /Path (C:/Windows/Fonts/meiryo.ttc)    /SubfontID 0 >> ;
/Meiryo-Italic     << /FileType /TrueType  /CSI [(Japan1) 6]  /Path (C:/Windows/Fonts/meiryo.ttc)    /SubfontID 1 >> ;
/Meiryo-Bold       << /FileType /TrueType  /CSI [(Japan1) 6]  /Path (C:/Windows/Fonts/meiryob.ttc)   /SubfontID 0 >> ;
/Meiryo-BoldItalic << /FileType /TrueType  /CSI [(Japan1) 6]  /Path (C:/Windows/Fonts/meiryob.ttc)   /SubfontID 1 >> ;

と追記して保存してから2

if(!"Meiryo" %in% names(postscriptFonts())){
    # UCS-2BE: Universal Character Set coded in 2 octets, Big endian
    postscriptFonts(Meiryo = CIDFont("Meiryo", "UniJIS-UCS2-H", "UCS-2BE"))
}

とすると、EPSファイルを作るときにfamily="Meiryo"と指定できるようになります。 なお、標準的な設定でのインストールではなく、*.ttcファイルの位置が異なる場合は、cidfmapに追記する文のファイルパス(C:/Windows/Fonts/)を変更してください。

14 プロットを重ねる

一つ目をプロットした後、par(new=T)と命令し、二つ目をプロットするだけで、高水準グラフィックス関数のプロットを重ねることができます。 ただし、

  • 題名は片方だけで指定する
  • 2つのプロットのxlimをあわせておき、横軸の表示はaxis関数でまとめて行なう
  • 二つ目のプロットの縦軸はaxis関数の第1引数を4にして行なう

などの工夫をする必要があります。

obs <- 3000 # 乱数で生成する標本サイズは3000
s <- rnorm(obs, mean=0, sd=1) # 正規分布からベクトルsに乱数を生成
xlim <- c(-4, 4) # 表示範囲
by <- 0.5 # ヒストグラムの間隔
s <- s[xlim[1]<s & s<xlim[2]] # 表示範囲外の値は除いておく
m <- 1.05 # mは上限調整用の係数
dm <- m*dnorm(0, 0, 1) # 分布関数の高さの上限dmを設定
hm <- obs*by*dm # ヒストグラムの面積は観測数*間隔で、分布関数の積分値は1になる。両者が同じになるように、高さの上限dmを設定
hist(s, breaks=seq(xlim[1], xlim[2], by), main="標準正規分布", ylab="obs.", xlab="", ylim=c(0, hm), col="white", border="black", angle="45")

par(new=T) # 重ね書きを指定

curve(dnorm(x, 0, 1), xlim[1], xlim[2], main="", ylab="", xlab="", axes=FALSE, col="black", ylim=c(0, dm), lwd=1.5) # 軸目盛や軸ラベルは表示しない
axis(side=4) # 右側に分布関数の縦軸目盛を表示する
mtext("density", side=4, line=3) # 右縦軸にラベルをつける

なお、curve関数は引数にadd = TRUEをつけることにより、一つ目と座標をあわせた重ね書きができます。上の例だとhistの後に、

curve(obs*by*dnorm(x, 0, 1), main="", ylab="", xlab="", col="gray", lwd=10, add = T)

と書くと、ヒストグラムのにスケールにあわせた(標準ではなくなった)正規分布を描くことができます。

15 複数のグラフを並べる

par(mfrow = c(m, n))の後にm*n回プロットを行なえば、mn列で合計m*n個のグラフを同時にプロットできます。

15.1 変則的な分割を行なう

1行目は1つのプロットで2列を使い、2行目は2つのプロットを表示するような変則的な同時プロットも、split.screen関数で入れ籠構造をつくれば表示できます。

# omaはページ全体の余白の指定
# par(mar=c(4, 4, 0, 0), mgp=c(2.5, 1, 0), oma = c(0, 0, 0, 0))
par(mar=c(4, 4, 1, 1), mgp=c(3, 1, 0), oma = c(1, 1, 1, 1))
# 2行1列の親領域をまずつくり、スクリーン番号の戻り値を得る
ss_p <- split.screen(c(2, 1)) 
# スクリーン番号を指定して、1行2列の子領域をつくる
ss_c <- split.screen(c(1, 2), ss_p[2])
# 親領域のスクリーン番号を指定して描画
screen(ss_p[1])
curve(dlnorm, 0, 5, xlab="")
# 子領域のスクリーン番号を指定して描画
screen(ss_c[1])
curve(dnorm, -3, 3, xlab="")
# 子領域のスクリーン番号を指定して描画
screen(ss_c[2])
curve(dexp, 0, 3, xlab="")

分割をやめるときは、以下のように終了します。

close.screen(all.screens = TRUE)

16 グラフを保存する

pngpostscriptなどでグラフィックスデバイスを開いた後、plotをして、dev.offでグラフィックスデバイスを閉じれば保存できます。

png(filename = "sin.png", 
    width = 800, height = 600, bg="white", type="cairo")
curve(sin(x), -pi, pi)
dev.off()

bgは背景色を示す引数で、transparentを指定すると透明です。DPIは72になります。

16.1 グラフィックスデバイスの開閉とプロットを分離

グラフィックスデバイスのオープンとプロットを分離したい場合は、遅延実行を応用します。 プロット部分だけ関数化できるので、同じ描画のコードを、画面確認,Web用PNG,TeX用EPS,R Markdownなどに使いまわしたいときに便利です。

save_as_png <- function(fname, plot_expression){
    png(filename = fname,
        width = 800, height = 600, bg="white", type="cairo")
    plot_expression
    dev.off()
}

save_as_png("sin.png", { curve(sin(x), -pi, pi) })

16.2 ディスプレイに表示した後に保存

plotしてディスプレイに表示した後に保存したくなった場合は、dev.copydev.copy2epsを使います。

curve(sin(x), -pi, pi)
dev.copy(png,
    file = "sin.png", width=600, height=400, type="cairo")
dev.off()

16.2.1 背景色

dev.copyは背景色の引数bgをとらないので、par(bg = "white")のように指定してください。

16.3 EPSファイルの用紙サイズ

postscriptでEPSファイルをつくるときは、widthheightpaper = "special"をつけておいた方が、回転などで取り回しが楽だと思います。paper = "special"は、widthheightにあわせて非定形用紙サイズが指定されるもので、pdfでは標準です。

postscript(file = "sin.eps", 
    width = 7, height = 7, paper = "special")
curve(sin(x), -pi, pi)
dev.off()

なお、widthheightはinch(=2.54cm)指定です。TeXで利用する人が多いと思いますが、1 inchが72 bpになり、bp単位でBoundingBoxが保存されます。上の例だと、%%BoundingBox: 0 0 504 504が入ります。TeXのgraphicsxパッケージのbbオプションはこのBoundingBoxを標準で入っています。

17 終わり

思い出せたところを列挙しました。後で追記するかも知れません。


  1. C:\Program Files\gs\gs10.0.0\lib\cidfmapなど、Ghostscriptのインストール先のlib以下にあります。↩︎

  2. /CSI [(Japan1) 6]Japan1は他の日本語フォントの記述を踏襲し、6は他のJapan1と被らないようにしただけです。ただし、試した限り、このように記述する必然性は無さそうでした。/SubfontIDは複数のフォントが入ったTTCファイルの保存位置を示すものです。↩︎