Google
WWWを検索
サイト内を検索

平面は2次元なので4変数以上のデータをプロットするのは不可能ですが、3変数であれば、3次元データを2次元に投影する立体グラフや等値線図(Contour line)を使えば、3変数の関係を把握できる図を描くことができます。手書きの時代の名残もあるのでしょうが、見えない裏面ができないため、等値線図を使うことが多いようです。Rの標準グラフィックスでも手軽に描くことができます。

1 データセットの作成

x, y, zの3つのベクトルを作成します。xyplotと同様ですが、zは行がx列がyの位置になる行列になります。x[3]y[2]に対応するzの値は、z[3, 2]に入ります。

数式をプロットする場合は、outer関数を用いると簡単にzの行列を作成することができます。以下では、(x, y)(1, 1)(x, y)(-1, -1)の距離をそれぞれ測り、近い方の値をzとしています。

d <- 0.1
a <- 2
y <- x <- seq(-a, a, d)
z <- outer(x, y, function(x, y){
   # xとyはスカラーではなくベクトル
   p1 <- c(1, 1)
   p2 <- c(-1, -1)
   p  <- matrix(c(x, y), length(x))
   dist <- function(p, p0) sqrt(apply((t(p) - p0)^2, 2, sum))
   pmin(dist(p, p1), dist(p, p2))
})

2 等値線図をプロット

プロットは簡単にできます。

contour(x, y, z)

素朴なので、見栄えを改善していきましょう。plotと同様の引数lty, lwd, col, axes, frame.plotなどが取れる他1、等値線図用のオプションがつけられます。

contour(x, y, z,
   levels = c(0.5, 1, 1.5, 2), 
   nlevels = 4, # 不要
   drawlabels = TRUE,  # 不要
   labels = c("a", "b", "c", "d"), 
   labcex = 1.0, 
   method = "flattest", # 不要
   vfont = c("serif symbol", "bold"))

levelsは、等値線を引くzの値です2

nlevelsは、等値線を引くzの値の数で、levelsを指定しないときのみ意味があります。

drawlabelsは、等値線にラベルをつけるかあらわす真偽値で、省略時はTRUEになります。

labelsは、等値線につけるラベルの指定で、省略時はlevelsが入ります。

labcexは、ラベルのフォントサイズです。

methodは、ラベルをつける位置になります。simple, edge, flattestが指定できますが、省略値の等値線が水平に近いところにラベルを描くflattestで間に合うことが多いと思います。 vfontは、ラベルのフォントで、?Hersheyで確認できるHershey vector fontsのtypefaceとfontindexを指定します。font familyは指定できないので、好みのフォントに変更はできません。symbolが入ったtypefaceを指定すると、アルファベットを対応するギリシャ文字表示にできます。

3 等値線図に色を塗る

色を塗る場合は、先に描画領域を作り、頭にドットのついた.filled.contourで色を塗ったあとに、add = TRUEをつけたcontourで等値線を描きます。

plot(NULL, xlim=c(min(x), max(x)), ylim=c(min(y), max(y)), 
   frame.plot = FALSE, xlab = "x", ylab = "y",
   panel.first = {
      levels <- c(0.5, 1, 1.5, 2)
      crp <- colorRampPalette(c("pink", "white")) # グラデーション作成関数をつくる
      .filled.contour(x, y, z, levels = c(0, levels, max(z)), col = crp(length(levels) + 1))
      contour(x, y, z, levels = levels, labcex = 1.0, add = TRUE) 
   }
)

panel.firstは、描画領域を作ったあと、データをplotする前に呼び出すコードブロックを指定する引数で、低水準関数を入れておくと先に描画します。 .filled.contourcontourで、levels引数の意味が異なるのに注意してください。.filled.contourは連結した区間を指定する必要があり、contourに渡すlevelsに両端を足しています。区間指定に使うベクトルの要素は区間ほより1つ多くなるため、colに渡す数はlevelsの要素より1つ多いだけです。 plotNULLを指定していますが、データを入れれば最後に描画されます。

4 色分け図に等値線を描く

色分けしたいだけの場合filled.contourを使うほうが手っ取り早いです。等値線の上書きもできます。

par(mar = c(4.5, 4, 0, 0))
levels <- c(0.5, 1, 1.5, 2)
crp <- colorRampPalette(c("pink", "white"))
filled.contour(x, y, z, levels = c(0, levels, max(z)), col = crp(length(levels) + 1), 
   plot.axes = {
      axis(1)
      axis(2)
      contour(x, y, z, levels = levels, labcex = 1.0, add = TRUE)
   }
)

色分けの凡例が消せず、領域を分割して表示する場合にうまく作図できないので、状況にあわせて使い分けましょう。


  1. Rのグラフィカル・オプションと低水準描画関数を参照してください。↩︎

  2. 縦横に捜査して、境界値を超える2点を探し、2点のウェイト付き平均の点を境界線上の点としてリスト、各点から一つづつ、自分とはまだ線が引かれていない他の点の中で、もっとも近い点に線を引いていくことで、境界線を構成しているようです。↩︎