画像とグラフの重ね合わせ（gnuplot; 陽性者予測と実際の比較図の作成を題材に）

#導入
画像とグラフを重ね合わせる機会はそれなりにある（特に古い文献を扱う場合）．ここでは，画像とグラフをgnuplotでどう重ねるかについて，コロナ禍のなか話題になった，あるショッキングなグラフを題材にして述べる．

そのショッキングなグラフとは，東京五輪開催に伴う新規陽性者シミュレーションと実際を比較したこのグラフである：

https://twitter.com/toshiyatakeuchi/status/1421378542370054146

シミュレーションのグラフは，実際には新聞記事の画像であり，その上に実際の新規陽性者数のグラフ（水色実線）が重なっている．今回は，これをgnuplotで再現する．

#やったこと
* 東京都新規陽性者の時系列データを作成する (bash)
* 元画像の原点と縮尺を決定する (gnuplot)
* 元画像とグラフを重ね合わせる (gnuplot)

#東京都新規陽性者の時系列データ作成
単にgnuplotの練習になるだけだと思ったが，日にちごとの新規陽性者数というドンピシャなデータが手に入らない．どうやら直接そのような形で提供されているものはないようで（単に調べ方が悪いという説も…），詳細データをシェルスクリプト (bash) でいろいろと下処理することになった．詳細データは[東京都オープンデータカタログサイト](https://catalog.data.metro.tokyo.lg.jp/dataset/t000010d0000000068/resource/c2d997db-1450-43fa-8037-ebb11ec28d4c)から取得した．

この詳細データは，陽性者一人一人の情報が書き込まれているもので，

* 5列目（公表年月日）のみを抜き出す
* 日付でgrep
* wcで列数を数える

という方針で日ごとの新規陽性者を数え上げた（エクセルでもいいと思う）．

シェルスクリプトは以下の通り（最後に中間ファイルの削除処理を行うので注意）：

```bash:data-proc.sh
#!/bin/bash

rawfile=130001_tokyo_covid19_patients.csv
daily=daily.txt

wget https://stopcovid19.metro.tokyo.lg.jp/data/130001_tokyo_covid19_patients.csv

#日ごとの新規陽性者を数える関数
new_infec () {
	for day in $(seq -w ${2} 1 ${3}); do
		pat=$(cat ${daily} | grep "2021-${1}-${day}" | wc -l)
		if test ${pat} != "0"; then
			echo ${pat} >> patient_data.txt
		fi
	done
}

cut -d , -f 5 ${rawfile} > ${daily} #5列目だけ取り出し
new_infec 06 20 30 #06/20~06/30の陽性者を数える
new_infec 07 01 31 #07/01~07/31の陽性者を数える
new_infec 08 01 31 #08/01~08/31の陽性者を数える

nl -v 0 patient_data.txt > data.txt #06/20からの経過日数を追加
rm -f patient_data.txt ${rawfile} ${daily} #中間ファイルのお掃除
```

今回は，例の図に合わせて，06/20からの2か月強を対象に数え上げている．未来の日付を数え上げると新規陽性者0となるので，条件分岐で0のデータを出力しないようにした．単純に数えるだけが目的ならば，2019年~2020年初頭に実際に新規陽性者が0だったときのデータを弾いてしまうので，この分岐は有害になる可能性があることを追記しておく．

data-proc.shを実行して出力されるファイルがこんな感じ（1列目は06/20を起点にした経過日数，2列目は東京都の新規陽性者数．）：

```:data.txt
     0	376
     1	236
     2	435
     3	619
     4	570
     5	562
     6	534
     7	386
     8	317
     9	476
    10	714
……
```

#元画像の原点の位置調べ
陽性者予測の画像は

* [東京新聞WEB（2021年6月11日）五輪開催で感染者が急増、東京1日1000人に…政府が試算　パラリンピック開幕を直撃](https://www.tokyo-np.co.jp/article/110157)

から拝借した．この画像ファイルを```yosoku.jpg```とする．画像利用にあたっては，

* [東京新聞WEB・著作権に関するQ&A](https://www.tokyo-np.co.jp/info/copyrights/qa)

を参考にした．本記事はこの項目のうち「引用」に該当すると判断している[^1]．
[^1]: 正確には，陽性者数シミュレーションと実際の陽性者数の比較をテーマにしたうえで，その題材として引用するものである．

まず，この画像をgnuplotで表示してみよう．画像が配置されているディレクトリでgnuplotを起動し，以下を入力する．

```gnuplot
plot "yosoku.jpg" binary filetype=auto with rgbimage
```

うまくいけば，画像の左下端がグラフ上の原点 (0, 0) に，1ピクセルの大きさがグラフ上で幅1となるようにプロットされているはずである（画像は東京新聞WEB 2021年6月11日を改変）：
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575153/c730ed34-9eea-3326-0c9c-0ee3fce20062.png)

まず，このグラフ画像の原点（人数0・6月20日）の座標を調べたい．当該座標のx成分を```orig_x```，y成分を```orig_y```としよう．画像の原点に相当するピクセルの座標値を調べて代入し，目論んだ位置と重なるかを確かめる．プロットウィンドウは自由に拡大/縮小できるのでそれも活用する．

```gnuplot
orig_x=72.0
orig_y=45.0
set parametric
replot orig_x,orig_y with point
```

![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575153/cbcf47c1-cdef-069e-62d2-e33af754a694.png)
（画像は東京新聞WEB 2021年6月11日を改変）

x座標値が0.5ほど右にずれていると判断したので再調整．

```gnuplot
orig_x=71.5
replot
```

![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575153/798cea12-3cf6-7145-33f0-35c6cd924e6d.png)
（画像は東京新聞WEB 2021年6月11日を改変）

こんなところだろうか．凝りだすとキリがないのでこの程度にしておく．

#元画像へプロットするための縮尺調べ
次に縮尺を調べる．「縮尺」とだけ言うとわかりづらいが，要は横軸の1日の幅・縦軸の1人がグラフ上でどの程度の幅になるかを調べたいということだ．この作業によって，新規陽性者の実際値をどうスケール変換すればうまくグラフと重ねることができるかがわかる．

今回は，格子が重なっていて都合がいい点である (70日 (=8月29日), 1000人) の座標値を調べることにする．この点のグラフ画像の原点に対する相対位置ベクトルを```(align_x, align_y)```とおこう．これは，おおまかにはピクセル座標の差を調べればよい．調べたら，プロットして位置を確認する．

```gnuplot
align_x=417.0
align_y=243.0
set autoscale xy
replot align_x+orig_x,align_y+orig_y with point
```

![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575153/2eb8268b-7fae-38fc-b6de-5aea8e4fd8d2.png)
（画像は東京新聞WEB 2021年6月11日を改変）
x座標値が右に1，y座標値が下に1.5ずれていると判断したので微調整．

```gnuplot
align_x=416.0
align_y=244.5
replot
```

![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575153/86c3ef67-2efd-778d-87e6-fb2888033300.png)
（画像は東京新聞WEB 2021年6月11日を改変）
いい感じ（自画自賛）．

この```align_x```と```align_y```を用いれば，データ```(d_x, d_y)```が次の座標値```(x, y)```にプロットされるべきであることがわかる：

```
x=orig_x+(align_x/70.0)*d_x
y=orig_y+(align_y/1000.0)*d_y
```

#元画像とグラフの重ね合わせ
以下のようなgnuplotバッチファイルを作った．

```gnuplot:comp.gpl
reset #精神安定剤

set terminal pngcairo size 960,1280 #縦長画像
set output "comp.png"
set size ratio -1 #アスペクト比保存
set autoscale xy

#枠なし・軸なし・凡例なし
unset border
unset tics
unset key

orig_x=71.5
orig_y=45.0
align_x=416.0  #70日間の幅
align_y=244.5  #1000人の幅

set label 1 at screen 0.1,0.95 "画像は東京新聞WEB 2021年6月11日\nまとりょーしか加筆 (緑色グラフ)\nデータ元: 東京都 新型コロナ陽性患者発表詳細"
#画像出典・データ提供元の表示

plot "yosoku.jpg" binary filetype=auto with rgbimage,\
"data.txt" using (orig_x+(align_x/70.0)*($1)):(orig_y+(align_y/1000.0)*($2)) with lines linewidth 6 linecolor rgb "forest-green"
set terminal pop #精神安定剤
```

次のような画像が出力される：
![comp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575153/d813a06e-9ccd-131d-cdf3-85d75a662196.png)
（画像：東京新聞WEB 2021年6月11日を改変，データ元：東京都 新型コロナウイルス陽性患者発表詳細）

みなさん感染対策は万全に．体調にはお気をつけて．
また，新型コロナウイルスに感染された方々の，一日も早い回復をお祈りします．

#参考
* きっかけとなった図 https://twitter.com/toshiyatakeuchi/status/1421378542370054146
* 東京都 新型コロナウイルス陽性患者発表詳細 https://catalog.data.metro.tokyo.lg.jp/dataset/t000010d0000000068/resource/c2d997db-1450-43fa-8037-ebb11ec28d4c
* 東京新聞WEB（2021年6月11日）https://www.tokyo-np.co.jp/article/110157
* 東京新聞WEB 著作権に関するQ&A https://www.tokyo-np.co.jp/info/copyrights/qa