Tex, python, illusrator, VPSの学生ノート

latotex-blog

Python

Pythonの標準ライブラリだけでRose Diagramを作る方法!

投稿日:






PythonでRose Diagramを作るとき、Windroseを使う例が多いですが、インストールがめんどくさいので、標準ライブラリだけで作ることにしました。

やっていることは単純で、

1.円を描く 2.度数を求める 3.棒グラフを描く の3stepです。

今回は、大阪府における新型コロナウイルス感染症患者の発生状況(令和2年3月29日20時30分現在)のデータを取り上げ、

入院中、または入院調整中の方のなかで、軽症・無症状・重症がどれほどいるのかを年代ごとにRose Diagramで表現しました。

大阪府のデータを使っていますが、あくまでもrose diagramを作る練習なので、この図から得られる結果についてすべての責任を持つことはできません。予めご了承ください。正しい情報を得たい方は、上にリンクを張ってある大阪府のサイトからご確認ください。

スポンサーリンク

Pythonコード

#!/usr/bin/env python3

#必要なものを宣言
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.lines import Line2D

#保存する場所
DIR1 = '/home/User/rose_diagram/figs/'

#解像度の指定
set_dpi = 100

#指す内容は同じだが、
#age_rangeは円のグリットのラベル
#age_listはexcelファイルからの抽出に使う
age_range = np.linspace(10, 80, 8, dtype=int)
age_list = np.arange(0, 90, 10)

#軽症・無症状・重症のリスト
symptom_list = [ 'mild','asymptomatic','severe']
symptom_color = ['y', 'g', 'r']

nage, nsym = len(age_range), len(symptom_list)


#ezcelファイルの読み込み
df1 = pd.read_excel("rose-diagram_data_rev.xlsx")


#ここから作図
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(projection='polar')

#円の設定
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
ax.set_thetagrids(np.arange(0, 360, 45), labels=age_list, fontsize=12)
ax.set_rgrids(np.arange(0, 30, 5), angle=0, weight= 'black')

#dataframeをnp.arrayで使いやすいように調節
age = df1.iloc[:, 0]
sym = df1.iloc[:, 1]
data = np.array([age,sym]).T

#legendとangle位置調整につかう
bar_angle = np.arange(23, 383, 45)
legend_angle = np.deg2rad(270)

#必要なデータをリストで受け渡すための準備
ndata = []


for isym in range(nsym):
	lsym = symptom_list[isym]

	for iage in range(nage):
		lage = age_range[iage]

		#年齢と症状が一致するものに並び替える
		var0 = np.where((data[:,0] == lage) & (data[:,1] == lsym))

		vshape = data[var0].shape[0]
		ndata.append(vshape)

		#if~をする理由は、最後のループ結果をndataとしたいため
		if iage == nage-1 and isym == nsym-1:
			ndata = np.array(ndata)

			#このaの要素が棒グラフをかくための度数
			a = np.reshape(ndata, (nsym, -1))
			ybar = a.tolist()

			#棒グラフを作成
			for iybar in range(nsym):
				ax.bar(np.deg2rad(bar_angle), ybar[iybar],
					width=np.deg2rad(45), bottom=0.0, color=symptom_color[iybar],
					edgecolor='k', alpha=0.5, zorder=iybar)


	#ax.barにlabelを指定しても、legendが出力されなかったので、自力でつくる
	custom_lines = [Line2D([0], [0], color=symptom_color[0], lw=4),
					Line2D([0], [0], color=symptom_color[1], lw=4),
					Line2D([0], [0], color=symptom_color[2], lw=4),]

	ax.legend(custom_lines, symptom_list, loc="lower center",
				ncol=nsym, columnspacing=1, fontsize=18, frameon=False,
				bbox_to_anchor=(.5 + np.cos(legend_angle)/2, .35 + np.sin(legend_angle)/2))


#pngで保存
fileo1 = DIR1 +'test'+'.png'
plt.savefig(fileo1,dpi=set_dpi, transparent=False)


    

使用したexcelの中身

Pythonコードでいう、df1の中身を一応載せておきます。ageとsymtomを列とした133×2のdataframeを使っています。

      age       symptom
0     40          mild
1     60          mild
2     70  asymptomatic
3     60  asymptomatic
4     60          mild
5     50          mild
6     20          mild
7     60          mild
8     30  asymptomatic
9     40        severe
10    30          mild
11    20          mild
12    70          mild
13    50  asymptomatic
14    30  asymptomatic
15    30          mild
16    50          mild
17    70          mild
18    70          mild
19    30          mild
20    20          mild
21    70          mild
22    60        severe
23    50          mild
24    80        severe
25    50          mild
26    50          mild
27    20          mild
28    60        severe
29    40          mild
..   ...           ...
103   40          mild
104   70          mild
105   20          mild
106   20          mild
107   30          mild
108   20          mild
109   50          mild
110   30          mild
111   40          mild
112   30  asymptomatic
113   20          mild
114   20          mild
115   40          mild
116   40          mild
117   10  asymptomatic
118   70          mild
119   60          mild
120   30          mild
121   60          mild
122   50          mild
123   30          mild
124   40          mild
125   20          mild
126   30          mild
127   60          mild
128   60          mild
129   20          mild
130   20          mild
131   50          mild
132   70          mild

[133 rows x 2 columns]

スポンサーリンク

参考にしたサイト様

Rose Diagramを作る作業の流れ (こちらのサイト様は度数を求めるためにヒストグラムを利用しています)
http://geologyandpython.com/structural_geology.html
matplotlib公式 (legendの配置の仕方を参考にしました)
https://matplotlib.org/3.2.1/gallery/pie_and_polar_charts/polar_legend.html


-Python

Copyright© latotex-blog , 2020 All Rights Reserved Powered by STINGER.