Rで色付き等高線図を描く

#要約
RStudioで以下のような色付き等高線図の描き方を紹介します。
![20201225-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/4e2ced6a-76e5-0a8a-226a-eede7e76e62d.png)

- 等高線は、数式で与えられているものとします。上の図の場合は、円の式（$z=x^2+y^2$）で描画しています。

#環境
- OS: Windows10
- R: R x64 4.0.3
- RStudio: Version 1.3.1093

#説明
まずは、ソースコード（Rファイル）とその結果をお見せします。後ほど、説明をいたします。
##ソースコード

```test1.r
n <- 100
x <- seq(-1,1,length=n)
y <- seq(-1,1,length=n)
z <- matrix(0, n, n)
for(i in 1:n){
  for(j in 1:n){
    z[i,j] <- x[i]^2 + y[j]^2
  }
}

filled.contour(x, y, z,
               nlevels = 10,
               col = cm.colors(10),
               plot.axes={
                 axis(1)
                 axis(2)
                 contour(x,y,z,nlevels=10,add=T)},
               key.axes=axis(4,seq(0,2,by=0.2)))
```

##結果
![20201225-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/4e2ced6a-76e5-0a8a-226a-eede7e76e62d.png)

##説明
`filled.contour()`は、行列データを元に等高線図（contour）を描く関数です。
[こちらのWebサイト](http://www.okadajp.org/RWiki/?%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%B9%E5%8F%82%E8%80%83%E5%AE%9F%E4%BE%8B%E9%9B%86%EF%BC%9A%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E5%9B%B3#yd58f0b8 "グラフィックス参考実例集：イメージ図 - RjpWiki")の例を引用すると、

```example1.r
data(volcano)
filled.contour(volcano, color = terrain.colors, asp = 1)
```

というコードを実行すると、以下の等高線図が描画されます。
![20201225-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/6e0773c2-b6b2-bebe-7cd0-d64ba137fde5.png)

このとき、`filled.contour()`に渡した`volcano`というデータは、Rにはじめから組み込まれているデータセットであり、87×61の行列です。
（以下に、`volcano`のデータの一部を示します。）
![20201225-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/e875a6f2-b893-87b2-b6e3-3bd69550107e.png)

今回は、与えられた数式を用いて等高線図を描きたいという状況ですが、`filled.contour()`は行列データしか受け付けてくれません。そこで、

- 数式を元に行列データを作成し、
- その行列データを`filled.contour()`に渡す

というステップを踏むことになります。

さて、最初にお見せしたソースコードを追い始めます。

```test1-1.r
n <- 100
x <- seq(-1,1,length=n)
y <- seq(-1,1,length=n)
z <- matrix(0, n, n)
```

`n <- 100`は、作成する行列の大きさを指定しています。この数字が小さいと、出力される等高線図が粗くなりますので、必要十分な大きさの整数を設定してください。

`x <- seq(-1,1,length=n)`と`y <- seq(-1,1,length=n)`で、横軸（x軸）と縦軸（y軸）のベクトルを作成します。ここではともに、`-1`から`1`までを範囲としています。

`z <- matrix(0, n, n)`で、`filled.contour()`に渡す行列を作成しはじめます。まず、0で埋め尽くされたn×n（ここでは100×100）の行列を作成します。

そして、以下の二重の`for`文で、`z`に具体的な値を代入していきます。数式は$x^2 + y^2$であり、円のグラフです。

```test1-2.r
for(i in 1:n){
  for(j in 1:n){
    z[i,j] <- x[i]^2 + y[j]^2
  }
}
```

ここまでで、等高線図を作成するデータができあがりました。
ここからは、実際に等高線図を描画するコードです。

```test1-3.r
filled.contour(x, y, z,
               nlevels = 10,
               col = cm.colors(10),
               plot.axes={
                 axis(1)
                 axis(2)
                 contour(x,y,z,nlevels=10,add=T)},
               key.axes=axis(4,seq(0,2,by=0.2)))
```

`filled.contour()`の詳細は、[公式ドキュメント](https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/filled.contour "filled.contour function | R Documentation")をご確認ください。

最初に、先ほど作成した`x`、`y`、`z`を渡します。

`nlevels`とは、等高線の領域の個数です。今回の等高線図では、`0.0`から`2.0`までが`0.2`刻みで等分割されています。この分割数が`nlevels`です。

`col`は色の指定です。今回は、`nlevels = 10`としたので、10個のカラーコード（#FFFFFFのようなコード）を渡す必要があります[^1]。ところで、Rにはいくつかのカラーコードのデータセットが初めから組み込まれています。今回は、`cm.colors()`を用いて10個のカラーコードを取得しています。

`plot.axes`で、横軸・縦軸を描画します。`axis(1)`、`axis(2)`は、既存の軸データ（`x`および`y`）を用いて横軸・縦軸を描画することを指示しています。
ここではさらに、`contour(x,y,z,nlevels=10,add=T)`を追加することで、等高線の描画もしています。これがないと、等高線のない、色で塗り分けられただけの等高線図が出力されます。
![20201225-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/1eff7b3d-c9af-3fb6-8d6b-c7aff16efeb2.png)
`x,y,z,nlevels=10`は先述の説明のとおりです。`add=T`はグラフの重畳を許可するという意味です。これがないと、色で塗り分けられた等高線図を削除した状態で、等高線だけが描画されることになります。

最後の`key.axes=axis(4,seq(0,2,by=0.2))`は、等高線図の右側にあるカラーバーの表示です。`0`から`2`の`0.2`刻みで目盛りを書き込むことを指示しています。


#参考Webサイト
https://stackoverflow.com/questions/46160054/how-do-i-add-color-to-a-contourplot-in-lattice

#姉妹記事
[Rで３次元の色付き等高線図を描く](https://qiita.com/kaz0414/items/551ee79c9bbff25c13b2 "Rで３次元の色付き等高線図を描く - Qiita")

[^1]: `nlevels`よりも多くカラーコードを渡すと、先頭から`nlevels`分のカラーコードを用い、以降は無視されます。一方、`nlevels`よりも少なくカラーコードを渡すと、足りない分を、再び先頭のカラーコードから使用し始めます。仮に`nlevels = 10`で3つしかカラーコードを渡さなかった場合、例えば、1, 4, 7, 10は同じ色で塗りつぶされます。