ヒートマップ, 混合行列

参考

概要

混合行列 (Confusion Matrix) などと呼ばれるあの表を色付きで図示する. 色の濃さで数の大きさを表現する.

上の参考リンクでは色が連続して変化するように中間値補完が為されてるが, 私の知ってるgnuplotのバージョンではこれは再現できない. これをするには pm3d を使ったほうがいいと思う.

方法

Data Format

行列 (matrix) 形式でデータを与えることにする. すなわち, データ $z$ を $n$ 行 $m$ 列に並べたものをデータとする.

z11 z12 z13
z21 z22 z23
z31 z32 z33
z41 z42 z43

混合行列を図示する目的のためには行と列とに見出し (座標ではなくラベル) があるべきで, どうせならデータに含めたい. gnuplot の matrix data は行ごとのアイテム数は揃ってる必要があるので, 0行目0列目にはダミーデータを入れた上で, 1行目または1列目に見出しを入れられる.

xxxx Col1 Col2 Col3
Row1  z11  z12  z13
Row2  z21  z22  z23
Row3  z31  z32  z33
Row4  z41  z42  z43

with image

plot ... using <x>:<y>:<z> with image
paramsdefaultvalueexplanation
x--(int)データの $x$ 座標
y--(int)データの $y$ 座標
z--(double)データ. 対応する色が塗られる

ただし, matrix で読む場合は x, y は自動的に column 1, 2 として適切な値が入ってると見なしてよい.

columnheaders, rowheaders

plot ... matrix column rowheaders

データの一行目, 一列目の文字列を見出しだと思って, 二行目, 二列目以降のデータだけを使う.

Example

$data << EOM
xxxx Col1 Col2 Col3
Row1    1    2    3
Row2    2    4    6
Row3    4    8   12
Row4    8   16   24
EOM

unset key
set title 'Heatmap with image'

set cbrange [0:30]  # the range of colorbox
set palette cubehelix start -2 cycles 0 saturation 3 gamma 3 negative  # color scheme

plot $data matrix rowheaders columnheaders u 1:2:3 with image ,\
        '' matrix rowheaders columnheaders u 1:2:(sprintf("%g", $3)) with labels

格子線 (gridline)

set grid によってセル同士の境界に線を引きたい. デフォルトだとセルの色塗りは gridline の後に行われて上書きされるので set grid front とする. ltlc, lw で線のスタイルは調整する.

$data << EOD
X a b c d e
A 0.0 -0.06 -0.25 -0.56 -1.0
B 0.11 0.04 -0.13 -0.45 -0.88
C 0.44 0.38 0.19 -0.11 -0.55
D 1.0 0.93 0.75 0.43 0.0
E 1.77 1.71 1.52 1.21 0.77
EOD

set grid front lw 1.5 lt -1 lc rgb 'white'
plot $data matrix rowheaders columnheaders w image not

xy に gridline を引いてもちょうど 0.5 ずれた, セルの真ん中に引くようになってしまう. なぜならセルはちょうど格子点 \( (x, y) \) に対して, \( (x-0.5, y-0.5) \ldots (x+0.5, y+0.5) \) という矩形領域を占めているためである.

ちょうど 0.5 ずらした格子線を手に入れるために小目盛り (minor tics) を利用する. ただし xy の大目盛りがラベルのために使われている (数値で指定されていない) ときは小目盛りは使えないことになっているので, x2y2 を使う.

まず x2, y2 を宣言し set linkxy と同期させる. これに小目盛り mx2, my2interval=2 で宣言することで, ちょうど半分に分割する目盛りを作れる. grid の引数に mx2tics, my2tics を追加すればよい.

変更点だけ書き出すと次の通り.

+set x2tics
+set y2tics
+set link x2
+set link y2
+set mx2tics 2
+set my2tics 2
-set grid front lw 1.5 lt -1 lc rgb 'white'
+set grid front mx2tics my2tics lw 1.5 lt -1 lc rgb 'white'

最後に余計なラベルや刻み線を消す処理を追加して結局

$data << EOD
X a b c d e
A 0.0 -0.06 -0.25 -0.56 -1.0
B 0.11 0.04 -0.13 -0.45 -0.88
C 0.44 0.38 0.19 -0.11 -0.55
D 1.0 0.93 0.75 0.43 0.0
E 1.77 1.71 1.52 1.21 0.77
EOD

set xtics scale 0  # 刻み線の長さ
set ytics scale 0
set x2tics format '' scale 0.01  # こちらもゼロにしたいがすると格子線まで消えてしまうので
set y2tics format '' scale 0.01
set link x2
set link y2
set mx2tics 2
set my2tics 2
set grid front mx2tics my2tics lw 1.5 lt -1 lc rgb 'white'
plot $data matrix rowheaders columnheaders w image not

となった.