グラフィックス参考実例集:その他

(グラフィックス参考実例集に戻る。Rのグラフィックスパラメータを参照する。)


MASS パッケージの eqscplot 関数は x,y 軸の単位を等しく取る plot 関数 -- 2005.01.13

両軸上の等間隔なスケール(1cm)で描かれる散布図を描きます。以下の例の上は plot 関数、下は eqscplot 関数を使った例です。

 left

sunflowerplot

同じ位置に複数のデータがある場合、「花びら」の数でその数を識別する散布図

> data(iris)
> sunflowerplot(iris[, 3:4], cex = 0.2, cex.f = 1, size = 0.035, seg.lwd =0.8)
 left

stars レーダーチャート、蜘蛛の巣図

関数starsで星形図を描くことができます。この図は、各データ間の関係を調べるというより、全体の傾向を見たり、サンプルの分類を行なうためのものです。引数にはデータフレームを指定します。この関数は各行に毎に一つずつ星形図を描きます。引数scaleがTRUEであれば[*1]、まず列毎に標準化が行なわれます。   関数starsは、内部で複数図表を用いていますから、複数図表と同時に使うことはできません。

> data(mtcars)
> stars(mtcars[, 1:7], key.loc = c(14, 2), main = "Motor Trend Cars : stars(*, full = F)", 
        full = FALSE)
 left

幹葉表示

グラフィックスというべきかどうか?度数分布表+ヒストグラムを同時に作成する賢い集計法。もう一つの長所は、簡単なデータの場合、生データがそのまま保存できること。

> data(islands) # 世界の大陸・島の面積
> stem(log10(islands)) # 常用対数値

 The decimal point is at the |  # | の位置に小数点がある

 1 | 1111112222233444     # データ値 1.1 が6個ある
 1 | 5555556666667899999
 2 | 3344
 2 | 59
 3 |                      # データ 3.0,...,3.4 は無い
 3 | 5678                 # データ 3.5,3.6,3.7,3.8 がそれぞれ一つずつある
 4 | 012                  # 幹4、葉0 はアフリカの値 4.060924 に対応

Cohen-Friendly の associaion plot。

二元分割表の独立性からのずれを表示。(i,j) セルに対して d_{ij} = (f_{ij} - e_{ij}) / sqrt(e_{ij}) ( f_{ij} と e_{ij} は観測度数と、独立仮説の下での期待度数)とすると、各長方形の高さは d_{ij} に、幅は sqrt(e_{ij}) に比例し、箱の大きさは観測値と期待値の食い違いに比例。食い違いが正の場合は基準線より上黒色で、負の場合は基準線より下に赤色で描かれる。

assocplot1 <- function () {
    data(HairEyeColor)
    ## 男女統合
    x <- margin.table(HairEyeColor, c(1, 2))
    assocplot(x, main = "Relation between hair and eye color")
}
 left

stripchart データ数が少ない時は箱型図よりもベター?

stripchart1 <- function () {
   x <- round(rnorm(50), 1)
   stripchart(x)
}
 left

dotchart

関数dotchartはドットチャートを描きます。これは棒グラフと似た情報を図示しますが、値を点でプロットします。dotchartの最も簡単な使い方は、単にデータベクトルを渡すものです。

 dotchart(1:10)

引数labelsにデータのラベルを指定することもできます。

 dotchart(1:10, labels=paste("sample", 1:10))

 引数groupsに類別オブジェクトを指定すると、それに従ってデータをグループ分けして表示します。 dotchartの引数gdataにグループごとの集約値を指定すると、それがグループを表すラベルの位置に追加されます。

円グラフよりもベター?

つまりは棒の無い棒グラフ(下の棒グラフ版と比較せよ、よりシンプル?)

dotchart1 <- function () {
  data(VADeaths)
  dotchart(VADeaths, main = "Death Rates in Virginia - 1940")
}
 left

比較用の棒グラフ

barplot(VADeaths, beside=T, horiz=T)

 left

dotchart (2)

dotchart2 <- function () {
  data(VADeaths)
  op <- par(xaxs="i")# 0 -- 100%
  dotchart(t(VADeaths), xlim = c(0,100),
           main = "Death Rates in Virginia - 1940")
  par(op)
}
 left

点群の凸閉包 chull

chull.ex <- function () {
  old.par <- par(no.readonly = TRUE)
  on.exit(par(old.par)) 
  png("chull.png")
  X <- matrix(rnorm(2000), ncol=2)
  plot(X, cex=0.5)
  hpts <- chull(X)
  hpts <- c(hpts, hpts[1])
  lines(X[hpts, ])
  dev.off()
}
 left

自前のxy軸の例 (x軸は対数スケール、y軸は正規確率プロット) (2004.2.6, r-help 記事より)

つまりは対数正規確率紙。このグラフ上に対数正規分布の分布関数を画くと直線になる。結構複雑。さて、プロットそのものはどうして重ねたら良いのか。

lognormal.CDF.fn <- function(x.axis.title="Nf, Cycles"){
# 対数正規累積分布関数用グリッド
# まず、点無しでグリッドを画く  
# x軸は対数尺度。y軸は確率ラベルを持つが、正規確率尺度
z.min <- -5.5
z.max <- -z.min
z.norm <- seq(z.min, z.max, length=101)
plot(NA, NA, xlim=c(3, 7), ylim=c(z.min, z.max), type="n", xaxt="n",
     yaxt="n", frame = FALSE, xlab = "", ylab = "Cumulative Probability (Fraction less than N)")
#
# x軸を対数尺度で画く
axis(side = 1, labels = FALSE, at = c(3, 4, 5, 6, 7), line = 0., tick=TRUE, outer = FALSE)
text(x=c(3, 4, 5, 6, 7), y=rep(z.min-1.0, 5), rep("10", 5), xpd = NA, cex=1.)
text(x=c(3, 4, 5, 6, 7)+ 0.1, y=rep(z.min-0.8, 5)+0.08, 
     c("3", "4", "5", "6", "7"), xpd = NA, cex=0.8)
text(x=5.05, y=z.min-1.6, x.axis.title, xpd=NA, cex=1.)
# Draw the interior log tick marks
for (i in 3:6){
axis(side=1, at=log10(c(2, 3, 4, 5, 6, 7, 8, 9))+ i,   cex=1, labels=NA,, line = 0, tck = -0.01)
text(x=log10(c(2, 3, 4, 5, 6, 7, 8))+ i, y=rep(z.min-0.7, 7), 
     c("2", "3", "4", "5", "6", "7", "8"), xpd = NA, cex=0.7)
}
#
# y軸を正規確率プロットで画く
probs <- c(1e-7, 1e-6, 1e-5, 1e-4, 0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.3, 0.4, 
           0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.98, 0.99, 0.995, 0.998, 0.999, 0.9999, 0.99999, 
           0.999999, 0.9999999)
z.vals <- qnorm(probs)
axis(side=2, at=z.vals , labels=NA, line = 0, tck = -0.01)
text(x=rep(3.-0.4, 4),  y= -0.1+qnorm(c(1e-7, 1e-6, 1e-5, 1e-4)), cex=0.8, 
     xpd = NA, labels=rep("10", 6))
text(x=rep(3.-0.3  , 4),  y=  0.1+qnorm(c(1e-7, 1e-6, 1e-5, 1e-4)), cex=0.6, 
     xpd = NA,labels=c("-7", "-6", "-5", "-4"))
text(x=rep(3.-0.25, 6),  y= qnorm(c(0.001, 0.01, 0.1, 0.5, 0.9, 0.99, 0.999)), cex=0.7,  
     xpd = NA,labels=c("0.001", "0.01", "0.1", "0.5", "0.9", "0.99", "0.999"), adj=1)
text(x=rep(3.-0.4, 4),  y= -0.1-qnorm(c(1e-7, 1e-6, 1e-5, 1e-4)), cex=0.8,  
     xpd = NA, labels=rep("1-10", 6))
text(x=rep(3.-0.27  , 4),  y=  0.1-qnorm(c(1e-7, 1e-6, 1e-5, 1e-4)), cex=0.6,  
     xpd = NA,labels=c("-7", "-6", "-5", "-4"))
box()
}
normalaxis.jpg

文字列の描画 text

関数textで、図表領域上の任意の位置に文字列を描画することができます。座標値、文字列ともにベクトルで指定することができます。

text(x, y, labels)

によって、各点( x[i] , y[i] )に文字列 labels[i] を描きます。linesやpointsと同様、x、yを別々に指定する代わりに、x、y成分を持ったリスト、または2列の行列を指定しても構いません。 なお、textで文字列を描画する際は、文字列が余白にはみ出しても描かれます。つまり、作図パラメータxpdは常にTRUEとして扱われますので注意して下さい。 グラフ上の任意の場所に文字列を書き込みたい時などには、textを locatorと組み合わせて使うと便利です。以下の例では、locator により座標を一つだけ得て、その位置に文字列を描き込んでいます。

plot(1:10)
text(locator(1), labels = "異常値")
 left

画面の4隅に文字・式を書く mtext

余白に文字列を書き込むにはmtextが便利です。

mtext(text, side, line, at)

引数textに書き込む文字列を指定し、 sideには余白のサイド番号、lineには図形領域から何行離すかを指定します。

mtext1 <- function () {
  old.par <- par(no.readonly = TRUE); on.exit(old.par) # 作図パラメータの退避と終了時復帰
  png("mtext1.png") # png デバイスを開く
  plot(1:10, (-4:5)^2, main="Parabola Points", xlab="xlab")
  mtext("10 of them")
  for(s in 1:4)
    mtext(paste("mtext(..., line= -1, {side, col, font} = ",s,
          ", cex = ", (1+s)/2, ")"), line = -1,
          side=s, col=s, font=s, cex= (1+s)/2)
    mtext("mtext(..., line= -2)", line = -2)
    mtext("mtext(..., line= -2, adj = 0)", line = -2, adj =0)
  dev.off() # デバイスを閉じる
}
 left

文字列に関する作図パラメータ

文字列描画に関する作図パラメータには以下のものがあります。これらによって、字の大きさ、文字列の描画方向などを設定することができます。

長さ(inch単位)を現在のプロット領域の実際の単位に変換する xinch, yinch 関数 (2004.3.9)

例1

## プロット記号の右 0.12 インチにラベルを書く
## この例では xinch(0.12) は 0.5295534 に変換される
data(mtcars)  # 組み込みデータ mtcars 読み込み
with(mtcars, { # mtcars の成分を展開した環境中で作図
     plot(mpg, disp, pch=19, main= "Motor Trend Cars",
     text(mpg + xinch(0.12), disp, row.names(mtcars), adj = 0, cex = .7, col = 'blue')
})
 left

例2

矩形を描く rect() 関数 をみよ。

画面を分割し、それぞれに描画。 layout 関数

layout 関数による画面の4分割とレイアウトの確認

layout1 <- function (n) {
  oldpar <- par(no.readonly = TRUE); on.exit(par(oldpar)) # 終了時パラメータ復帰
  # layout 関数で画面を横に 3:1、縦に1:3 の4画面に分割
  # 副画面の番号を [1,1] -> 2, [1,2] -> 0, [2,1] -> 1, [2,2] -> 3 とする
  nf <- layout(matrix(c(2,0,1,3),2,2,byrow=TRUE), c(3,1), c(1,3), TRUE)
  layout.show(nf) # レイアウトを確認したければこうする
  ## なぜか png デバイスは複数画面を一度に表示しないので遠回り
  pp <- recordPlot() # X11 デバイスへの出力を記録
  png("layout1.png") # png デバイスを開く
  replayPlot(pp) # pp に記録された画像を png デバイスへ出力
  dev.off() # デバイスを閉じる
 }
layout1.png

layout 関数の使用例。x,y データの散布図の上・右に x,y データの棒グラフを表示

layout2 <- function (n) {
  oldpar <- par(no.readonly = TRUE); on.exit(par(oldpar)) # 終了時パラメータ復帰
  x <- pmin(3, pmax(-3, rnorm(50))) # 50個の正規乱数. -3以下(3以上を)を-3 (3) に置き換え
  y <- pmin(3, pmax(-3, rnorm(50))) # 50個の正規乱数. -3以下(3以上を)を-3 (3) に置き換え
  xhist <- hist(x, breaks=seq(-3,3,0.5), plot=FALSE) # 棒グラフ情報を記録
  yhist <- hist(y, breaks=seq(-3,3,0.5), plot=FALSE) # 棒グラフ情報を記録
  top <- max(c(xhist$counts, yhist$counts))
  xrange <- c(-3,3)
  yrange <- c(-3,3)
  # layout 関数で画面を横に 3:1、縦に1:3 の4画面に分割
  # 副画面の番号を [1,1] -> 2, [1,2] -> 0, [2,1] -> 1, [2,2] -> 3 とする
  # 番号 0 の副画面には何も描かない(?) 
 nf <- layout(matrix(c(2,0,1,3),2,2,byrow=TRUE), c(3,1), c(1,3), TRUE)
  # layout.show(nf) # レイアウトを確認したければこうする
  par(mar=c(3,3,1,1)) #番号1の副画面の余白指定
  plot(x, y, xlim=xrange, ylim=yrange, xlab="", ylab="") # 番号1の副画面にプロット
  par(mar=c(0,3,1,1)) #番号2の副画面の余白指定
  barplot(xhist$counts, axes=FALSE, ylim=c(0, top), space=0) # 番号2の副画面にプロット
  par(mar=c(3,0,1,1)) #番号3の副画面の余白指定
  barplot(yhist$counts, axes=FALSE, xlim=c(0, top), space=0, horiz=TRUE) # 番号3の副画面にプロット
  ## なぜか png デバイスは複数画面を一度に表示しないので遠回り
  pp <- recordPlot() # X11 デバイスへの出力を記録
  png("layout2.png") # png デバイスを開く
  replayPlot(pp) # pp に記録された画像を png デバイスへ出力
  dev.off() # デバイスを閉じる
 }
layout2.png

スクリーン分割 split.screen

関数split.screenを使って、作図可能領域内にいくつかの異なる大きさの副画面を定義することができます。個々の副画面には通常の方法でグラフを描くことができます。 これは作図パラメータ mfrowやmfcolを用いた複数図表に似ていますが、規則的な画面分割に限らず、自由に副画面を定義することができ、各副画面で座標入力を行なうこともできます。 重なりを持った副画面を定義することも可能です。また、以下の作図パラメータが各々の副画面ごとに独立して管理されます。

adj  bty  cex  col  crt  err  exp  font  
lab  las  lty  lwd  mar  mex  mgp  new  
pch  pty  smo  srt  tck  usr  xaxp  xaxs  
xaxt  xpd  yaxp  yaxs  yaxt     

なお、split.screenは内部で複数図表を利用しているので、副画面で複数図表を用いることはできません。また、副画面に外周は作れません。

副画面の定義

副画面を定義するには、split.screenを使います。 引数には、分割方法を定義する長さ2のベクトルあるいは (定義する副画面の個数) × 4 の行列を与えます。 分割の結果、副画面の縦あるいは横が全画面の半分より小さくなれば,その時定義したすべての副画面について作図パラメータcexとmexが 0.5に設定されます。

ベクトルによる分割

split.screenにベクトル c( m , n ) を与えると、作図パラメー タmfrowによる規則的な分割と同じように、縦を m 個、横を n に分割します。例えば、上下二つに分割するには以下のようにします。

 split.screen(c(2,1))
[1] 1 2

分割の結果できた各副画面は番号によって管理されます。split.screen は分割の結果できた副画面の番号を返します。上記の例では上側が副画面1、下側が副画面2になります。引数screenに分割する副画面の番号を指定することによって、その副画面をさらに分割することができます。例えば、先ほどの例でできた副画面2をさらに3つに分割するには、

split.screen(c(1,3), screen = 2)
[1] 3 4 5

とします。

行列による分割

split.screenに (定義する副画面の個数) × 4 の行列を与えて画面定義を行なうこともできます。この場合は各行が個々の副画面を定義します。各行には、副画面を定義する画面の左下隅を (0, 0),右上隅を (1, 1) とする座標系で、各副画面の大きさと位置を左下隅のx座標、右上隅のx座標、左下隅のy座標、右上隅のy座標 の順で与えます。副画面は互いに重なりがあっても構いません。

(例1)。screen 関数の使用例

screen 関数はディスプレイを幾つかのスクリーンに分割し、それぞれにグラフィックスを書き込む。この例ではスクリーン 3,5 (スクリーン 2 がスクリーン 3,4,5 に分割されている) には書き込みが無い。

screen1 <- function () {
  par(bg = "white")           # 既定の背景色を白にする
  split.screen(c(2,1))        # ディスプレイを上下二つのスクリーンに分割
  split.screen(c(1,3), screen = 2) # スクリーン 2 (下半分)を更に横に三分割
  screen(1) # スクリーン 1 への書き込みを始める
  plot(10:1)
  screen(4) # スクリーン 4 への書き込みを始める
  plot(10:1)
  close.screen(all = TRUE)    # スクリーン分割モードを終了
}
 left

(例2) スクリーン 2 がスクリーン 3,4 に分割されている。

screen2 <- function () {  
  split.screen(c(2,1))        # ディスプレイを上下二つのスクリーンに分割
  split.screen(c(1,2),2)      # 下のスクリーンを更に横に二分割
  plot(1:10)                  # 既定で最後(screen 3)がアクティブ
  erase.screen()              # ラベルを書くのを忘れたので一旦消す
  plot(1:10, ylab= "ylab 3")
  screen(1)                    # スクリーン 1 への書き込みを始める
  plot(1:10)
  screen(4)                    # スクリーン 4 への書き込みを始める
  plot(1:10, ylab="ylab 4")
  screen(1, FALSE)             # スクリーン 1 へ戻るが、消さない
  plot(10:1, axes=FALSE, lty=2, ylab="")  # 上書き
  axis(4)                     # チックマークを右軸に加える
  title("Plot 1")
  close.screen(all = TRUE)    # スクリーン分割モードを終了
}
 left

(例3) 画面を 3x4 分割し、順に表示

par(oma=c(0,0,2,0))             # 総合タイトル用に隙間を設ける
split.screen(figs=c(3,4))       # 画面を 3x4 分割(順に番号 1,2,...,12 が付く)
 [1]  1  2  3  4  5  6  7  8  9 10 11 12
for(i in 1:12) {screen(i); plot(1:10)}  # 各スクリーンに作図
close.screen(all=T)             # スクリーンへの作図を終了  
title(main='TITLE 1', outer=T)  # 総合タイトル
 left

分割したグラフィックス画面の一部をスキップする。frame, plot.new 関数 (2004.2.14, r-help 記事より)

frame 関数は plot.new 関数の別名

> par(mfrow=c(2,1))
> plot.new()            # 第一分割画面をスキップし、第二画面に作図
> hist(rgamma(100000,6463.7,scale=0.015471),xlim=c(0,120),main="Emergence")
> par(mfrow=c(2,1))
> plot.new()
> hist(rgamma(100000,6463.7,scale=0.015471),xlim=c(0,120),main="Emergence")
plot.new.jpg
> par(mfrow=c(2,2))
> hist(rgamma(100000,6463.7,scale=0.015471),xlim=c(0,120),main="Emergence")
> plot.new()
> plot.new()
> hist(rgamma(100000,6463.7,scale=0.015471),xlim=c(0,120),main="Emergence2")
plot.new2.jpg

高水準作図関数による図の重ね描き

 同じ単位のいくつかのデータを一枚の図にプロットするには、 plotと points、linesなどを利用することができます。しかし、異なる単位のデータを一つのグラフに描画する場合など、 いくつかの異なった座標軸を描きたいこともあります。 この場合、高水準作図関数によるプロットを重ね合わせるのが便利です。通常は高水準作図関数は作図の前に画面を消去しますが、par(new=T)とすることによってこれを抑制できます。例えば以下のようにすると2つの時系列プロットを重ね合わせることができます。後で右の余白に軸を書き加えますから、最初に右の余白を少し広げておきましょう。

> par(mar=c(5,4,4,4)+0.1)
> plot(1:100,type="l")
> par(new=T)
> plot(10:1, type="l", axes=F, xlab="", ylab="", lty=2)

このとき、二度めのplotによって軸と軸のラベルが重ね書きされるのを避けるため、 axes=F, xlab="", ylab=""としていることに注意して下さい。二度めのplotに対する軸は、

> axis(side=4)

とすることによって、現在の単位に従った、すなわち二度めのplotが描くはずだったy軸を図の右側の余白に描きます。この軸に対するラベルは、

> mtext(side=4, line=3, text="uwxyz")

として描きます。最後に凡例も付けてみましょう。位置はlocatorで読み込みます。

> legend(locator(1), 
       legend=c("abcde", "uwxyz"), lty=1:2)

複数のプロットを少しずらして重ねる (r-help 記事より、2004.11.02)

par(mai = c(3,1,1,1))
x <- runif(50)
plot(x, xlim = c(1, 500), ylim = c( -5, 1), bty = "l")
par(mai = c(2,1.5,2,1))
par(new = TRUE)
x <- runif(50)
plot(x, xlim = c(1, 500), ylim = c( -5, 1), bty = "l")
par(mai = c(1,2,3,1))
par(new = TRUE)
x <- runif(50)
plot(x, xlim = c(1, 500), ylim = c( -5, 1), bty = "l")
 let

スケールの違う y 軸を二つかく (r-help 記事より)

>   plot(1:10)     # まず最初のプロット(x 軸と y 軸(左側)が書かれる) 
>   par("usr")     # その時のユーザー座標系
[1]  0.64 10.36  0.64 10.36
>   par(usr=c(par("usr")[1:2], 100.8, 105.2))  # ユーザー座標系を変更(x 座標系はそのまま)
>   points(1:5, 105:101, col="red")  # 追加の点を変更座標系に赤色で書く(軸は書かれない)
>   axis(4)         # 変更座標系の(y)軸を右側に書く
 left

カラーピッカー

カラーチャートをクリックして色を取得

# L: division of RGB space.
# N: number of pick-up colors
colorPicker<-function(L=8,N=1){
  if(L<2){cat("L must be lager than 1\n");return(NULL)}
  D<-ceiling(L^(3/2)) # 3D->2D
  v<-seq(0,1,by=1/(L-1));r<-rep(v,L*L);g<-rep(v,L,e=L);b<-rep(v,e=L*L)
  col<-c(rgb(r,g,b),rep(rgb(1,1,1),D^2-L-3)) # construct color vector
  x<-rep(0:(D-1),D);y<-rep(0:(D-1),each=D) # plot coord.
  par.old<-par(mfrow=c(1,1))
  plot(0,xlim=c(0,D),ylim=c(0,D),type="o",xaxt="n",yaxt="n",ann=F,col="0") # whiteboard
  for(y in (D-1):0)for(x in 0:(D-1))
    rect(x,y,x+1,y+1,col=col[1+x+(D-1-y)*D],border=NA) # create color chart
  p<-locator(N);ret<-col[1+floor(p$x)+(D-1-floor(p$y))*D] # click point -> color
  par(par.old)
  ret
}

添付ファイル: filebarplotc.png 2777件 [詳細] filestars.png 2873件 [詳細] filelayout2.png 2808件 [詳細] filetwoyaxis.png 3237件 [詳細] filestripchart1.png 2775件 [詳細] filescreen1.png 2714件 [詳細] fileplot.new2.jpg 2906件 [詳細] filescreen2.png 2842件 [詳細] fileplot.new.jpg 2772件 [詳細] filemtext1.png 3105件 [詳細] filenormalaxis.jpg 3060件 [詳細] filechull.png 2875件 [詳細] fileassocplot1.png 2719件 [詳細] filemltplot.png 2753件 [詳細] fileeqscplot.png 2789件 [詳細] filelabel.png 2658件 [詳細] filedotchart1.png 2836件 [詳細] filesunflowerplot.png 2798件 [詳細] filexyinch.jpg 2829件 [詳細] fileoverlap.png 2656件 [詳細] filedotchart2.png 2935件 [詳細] filelayout1.png 1025件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-03-25 (土) 11:19:17