意外とハマってしまったので、今日は matplotlib で横軸(X 軸)を日時にする方法を備忘録。初歩的な内容。
といっても話は簡単で、numpy.datetime64
型または datetime.datetime
型 のリストを使えば matplotlib
側が日時を名義尺度ではなく間隔尺度として扱ってくれる、というだけ。今日は元データの日付文字列を日時オブジェクトに変換し忘れたままグラフの X 軸に使っており、大量の「日時風の文字列」が X 軸に並ぶので困惑していた。まあ、分かってしまえば何ということは無いね。つまらない凡ミスだった。
以下では例として、厚生労働省が公開する新型コロナウイルスのオープンデータから陽性者数・死者数をダウンロードしてグラフに描画するコードと、その実行結果を書いておく。
from datetime import datetime import matplotlib.pyplot as plt import numpy as np import pandas as pd plt.style.use("ggplot") # データをダウンロード。 # 元データでは日付が YYYY/MM/DD という書式で ISO 8601 と異なるため # 明示的に parse_dates オプションを使い pandas.Timestamp に変換。 url_prefix = "https://www.mhlw.go.jp/content" positive_daily = pd.read_csv(f"{url_prefix}/pcr_positive_daily.csv", parse_dates=[0]) death_total = pd.read_csv(f"{url_prefix}/death_total.csv", parse_dates=[0]) df = pd.merge(positive_daily, death_total, on="日付") df.rename(columns={"日付": "date", "PCR 検査陽性者数(単日)": "pcr_positive_daily", "死亡者数": "death_total"}, inplace=True) print("*** [df] ***\n{}".format(df)) print("*** [df.dtypes]***\n{}".format(df.dtypes)) # グラフプロット用にデータを取り出す PREFER_NUMPY = False # お好きに if PREFER_NUMPY: x = np.array(df.date, dtype=np.datetime64) y1 = np.array(df.pcr_positive_daily, dtype=np.int64) y2 = np.array(df.death_total, dtype=np.int64) else: x = df.date y1 = df.pcr_positive_daily y2 = df.death_total print("-" * 40) print("x:", x.dtype, type(x[0])) print("y1:", y1.dtype) print("y2:", y2.dtype) # 日付を横軸 (X 軸)、人数を1縦軸 (Y 軸) にグラフをプロット fig, ax = plt.subplots(1, 1) ax.plot(x, y1, color="C0", label="PCR Positive (daily)") ax.bar(x, y2, color="C1", label="Death (cumulative)") ax.legend() fig.savefig("foobar.png") # 画像出力 # plt.show() # Jupyter Notebook または GUI に表示
これを実行すると、次のように適度な間隔で日時ラベルが付いたグラフが描画され:
コンソールには次のようなメッセージが表示される:
*** [df] *** date pcr_positive_daily death_total 0 2020-02-14 7 1 1 2020-02-15 12 1 2 2020-02-16 6 1 3 2020-02-17 7 1 4 2020-02-18 7 1 .. ... ... ... 174 2020-08-06 1479 1032 175 2020-08-07 1595 1038 176 2020-08-08 1523 1039 177 2020-08-09 1486 1046 178 2020-08-10 836 1051 [179 rows x 3 columns] *** [df.dtypes]*** date datetime64[ns] pcr_positive_daily int64 death_total int64 dtype: object ---------------------------------------- x: datetime64[ns] <class 'pandas._libs.tslibs.timestamps.Timestamp'> y1: int64 y2: int64