2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-08-02

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

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

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

#やったこと

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

#東京都新規陽性者の時系列データ作成
単にgnuplotの練習になるだけだと思ったが,日にちごとの新規陽性者数というドンピシャなデータが手に入らない.どうやら直接そのような形で提供されているものはないようで(単に調べ方が悪いという説も…),詳細データをシェルスクリプト (bash) でいろいろと下処理することになった.詳細データは東京都オープンデータカタログサイトから取得した.

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

  • 5列目(公表年月日)のみを抜き出す
  • 日付でgrep
  • wcで列数を数える

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

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

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
……

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

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

を参考にした.本記事はこの項目のうち「引用」に該当すると判断している1

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

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

うまくいけば,画像の左下端がグラフ上の原点 (0, 0) に,1ピクセルの大きさがグラフ上で幅1となるようにプロットされているはずである(画像は東京新聞WEB 2021年6月11日を改変):
001.png

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

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

002.png
(画像は東京新聞WEB 2021年6月11日を改変)

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

orig_x=71.5
replot

003.png
(画像は東京新聞WEB 2021年6月11日を改変)

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

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

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

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

004.png
(画像は東京新聞WEB 2021年6月11日を改変)
x座標値が右に1,y座標値が下に1.5ずれていると判断したので微調整.

align_x=416.0
align_y=244.5
replot

005.png
(画像は東京新聞WEB 2021年6月11日を改変)
いい感じ(自画自賛).

このalign_xalign_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バッチファイルを作った.

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
(画像:東京新聞WEB 2021年6月11日を改変,データ元:東京都 新型コロナウイルス陽性患者発表詳細)

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

#参考

  1. 正確には,陽性者数シミュレーションと実際の陽性者数の比較をテーマにしたうえで,その題材として引用するものである.

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?