tak0kadaの何でもノート

発声練習、生存確認用。

医学関連は 医学ノート

x軸を共有したグラフ、複数のy軸を持つグラフを描く

  • plt.add_axes()を用いた方法よりgridspecを用いた方法の方がレイアウトに気を使わず簡単にグラフを描けた。plt.setp(ax0.get_xticklabels(), visible=False)plt.subplots_adjust(hspace=.0)が一方の軸を非表示にして、さらに2つのグラフをくっつけて描くのに重要である。
  • y軸を複数描くにはtwinx()を用いる

以下のデータは乱数ででっち上げたものである。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as mpathes
from matplotlib import gridspec
plt.style.use('seaborn-muted')

with open("data.csv") as f:
    data = f.readlines()

# 上図用データ
data = [l.strip("\n").split(",") for l in data]
label = [l[0].upper() for l in data][1:]
time = pd.to_datetime(data[0][1:])
data = [[float(j) for j in l[1:]] for l in data[1:5]]
unit = ["1000/uL", "%", "10000/uL", "IU/L"]
data[2] = [i/10 for i in data[2]]

# 下図用データ
sp_data = dict()
sp_data[pd.to_datetime("20170216")] = 1749.89
sp_data[pd.to_datetime("20170525")] = 1883.92
sp_data[pd.to_datetime("20180111")] = 1822.2
sp_data[pd.to_datetime("20180628")] = 1922.28

# プロット
fig = plt.figure()
# 縦に3分割する
gs = gridspec.GridSpec(3,1)
# そのうち上2つを上のグラフに
ax1 = plt.subplot(gs[:2])
ax2 = ax1.twinx() # y軸を追加
# 残り1つを下のグラフに
ax3 = plt.subplot(gs[2], sharex=ax1) # 上のグラフとx軸のスケールは共通

for i in range(3):
    ax1.plot(time, data[i], label=label[i]+" ("+unit[i]+")", marker="sdv^"[i])
ax1.plot([],[], label=label[3]+" ("+unit[3]+")", marker="sdv^"[3]) # LDH凡例用空データ
ax2.plot(time, data[3], marker="sdv^"[3], color="purple") # LDH実データ
ax1.grid(linestyle='--', linewidth=0.7)
ax1.legend(loc="upper left")

# 追加のy軸関連の設定
ax2.set_ylabel('LDH', color='purple')
ax2.tick_params('y', colors='purple')
ax2.grid(False)
# 上のグラフのx軸の表記を消去
plt.setp(ax1.get_xticklabels(), visible=False)
plt.setp(ax2.get_xticklabels(), visible=False)

# 下のグラフをプロット
line = ax3.plot(list(sp_data.keys()), list(sp_data.values()), marker="*", markersize=12, linestyle="--", linewidth=0.7)
ax3.set_ylim(ymin=1000)
patch = mpathes.Patch(color=line[0].get_color(), label="volume (mL)")
ax3.legend(handles=[patch])
ax3.grid(linestyle='--')

# 上下のグラフの隙間をなくす
plt.subplots_adjust(hspace=.0)
plt.show()