以前にPythonで時系列クラスタリングをするで、DTW(動的時間伸縮法)による時系列データのクラスタリングをやってみた。このときはPythonパッケージのtslearnを使ってクラスタリングをしたが、単にDTWによる時系列データ間の類似度(距離)を求めたいだけならfastdtwも使える。ただ、fastdtwではDTWの近似アルゴリズムを使用しているので、tslearnとfastdtwの結果を比べてみることにした。
Debian Buster(Dockerコンテナ)とJupyter Lab。
PythonでPDFの表からデータを抽出する(その2) で使用した帰国者・接触者相談センター(全相談件数)を使う。これは厚生労働省のホームページ地域ごとの感染状況等の公表についてからダウンロードできる「3.帰国者・接触者相談センターへの相談件数の推移(都道府県別・各日)・帰国者・接触者外来の受診者数の推移・うちPCR検査実施件数の推移(都道府県別・各日) 」のPDFに含まれるデータ。最近EXCELファイルが追加されたのでわざわざPDFからデータを抽出する必要はないのだが、ここではPythonでPDFの表からデータを抽出する(その2) の方法で作成したcsvを使う。都道府県ごとのデータがあるので、都道府県データ間の類似度をDTWで比べてみる。
PDFからcsvにしたデータをExcelで開くと次のような感じになる。
DTWを計算するためにtslearnとfastdtwをインストールする。
インストールしたライブラリのバージョン。
さらに、matplotlibのグラフで日本語表示できるように日本語フォントをインストールしておく。
PDFから抽出したデータを保存したcsv(000643758.csv)を読み込んで、このcsvに含まれる都道府県ごとの「帰国者・接触者相談センター(全相談件数)」を使う。期間は5月のひと月分。都道府県により絶対数に差があるので、0-1の範囲にデータを変換する。なお、欠損値があるとDTWによる計算でエラーになるので京都、滋賀、香川のデータは除外。
都道府県ごとのデータのプロット。
tslearnとfastdtwで都道府県データ間の距離をDTWで計算し、似ている/似ていない都道府県の組み合わせを求めてみる。
似ている都道府県の組み合わせトップ10は以下の通り。tslearnとfastdtwで違いはあるものの、最も距離が近い組み合わせの神奈川と富山はtslearnとfastdtwで同じ。
最も距離が短い神奈川と富山のプロット。ほぼ一致している。
最も距離が遠い岐阜と高知のプロット。確かにけっこう違う。
tslearnとfastdtwそれぞれで距離が短いトップ5を比較。以下のコードを上記コードのあとに追加する。
環境
Debian Buster(Dockerコンテナ)とJupyter Lab。
時系列データ
PythonでPDFの表からデータを抽出する(その2) で使用した帰国者・接触者相談センター(全相談件数)を使う。これは厚生労働省のホームページ地域ごとの感染状況等の公表についてからダウンロードできる「3.帰国者・接触者相談センターへの相談件数の推移(都道府県別・各日)・帰国者・接触者外来の受診者数の推移・うちPCR検査実施件数の推移(都道府県別・各日) 」のPDFに含まれるデータ。最近EXCELファイルが追加されたのでわざわざPDFからデータを抽出する必要はないのだが、ここではPythonでPDFの表からデータを抽出する(その2) の方法で作成したcsvを使う。都道府県ごとのデータがあるので、都道府県データ間の類似度をDTWで比べてみる。
PDFからcsvにしたデータをExcelで開くと次のような感じになる。
ライブラリなどのインストール
DTWを計算するためにtslearnとfastdtwをインストールする。
インストールしたライブラリのバージョン。
さらに、matplotlibのグラフで日本語表示できるように日本語フォントをインストールしておく。
データの準備
PDFから抽出したデータを保存したcsv(000643758.csv)を読み込んで、このcsvに含まれる都道府県ごとの「帰国者・接触者相談センター(全相談件数)」を使う。期間は5月のひと月分。都道府県により絶対数に差があるので、0-1の範囲にデータを変換する。なお、欠損値があるとDTWによる計算でエラーになるので京都、滋賀、香川のデータは除外。
%matplotlib inline import pandas as pd from sklearn import preprocessing import matplotlib.pyplot as plt # 日本語フォントの指定 plt.rcParams['font.family'] = 'TakaoGothic' DT_FROM = '2020-05-01' DT_TO = '2020-05-30' def normalize(df): cols = df.columns idx = df.index x = df.values min_max_scaler = preprocessing.MinMaxScaler() x_scaled = min_max_scaler.fit_transform(x) return pd.DataFrame(x_scaled, index=idx, columns=cols) def _load(csvpath): df = pd.read_csv(csvpath, index_col=0, header=[0,1], parse_dates=True, encoding='shift-jis') # 全国を除く「帰国者・接触者相談センター(全相談件数)」だけを選択 df_con = df.filter(like='帰国者・接触者相談センター(全相談件数)', axis=1).drop(columns=('全国', '帰国者・接触者相談センター(全相談件数)')) # カラム名を都道府県のみにする df_con.columns = df_con.columns.droplevel(level=1) # 0-1の範囲に正規化 df_con = normalize(df_con[DT_FROM:DT_TO]) # 欠損値(NaN)があるとDTWの計算ができないので除外 # 京都、滋賀、香川のデータを除外 df_con = df_con.dropna(axis='columns') #print(df_con.info()) #display(df_con.head()) ax = df_con.plot(legend=None) plt.show() return df_con df = _load('000643758.csv')
都道府県ごとのデータのプロット。
DTWの計算
tslearnとfastdtwで都道府県データ間の距離をDTWで計算し、似ている/似ていない都道府県の組み合わせを求めてみる。
%matplotlib inline from itertools import combinations import pandas as pd from sklearn import preprocessing from fastdtw import fastdtw from tslearn.metrics import dtw import matplotlib.pyplot as plt # 日本語フォントの指定 plt.rcParams['font.family'] = 'TakaoGothic' DT_FROM = '2020-05-01' DT_TO = '2020-05-30' def calc_dtw(l_sr): dict_dtw = {} for sr1, sr2 in combinations(l_sr, 2): distance, path = fastdtw(sr1.to_numpy(), sr2.to_numpy()) dict_dtw[(sr1.name, sr2.name)] = (dtw(sr1.to_numpy(), sr2.to_numpy()), distance) return dict_dtw df = _load('000643758.csv') # Seriesのリスト l_sr = [item for l, item in df.items()] # 都道府県間のDTWを計算 dict_dtw = calc_dtw(l_sr) print('\n似ている都道府県トップ10(DTW)') display(sorted(dict_dtw.items(), key=lambda x:x[1][0])[:10]) print('\n似ている都道府県トップ10(fastDTW)') display(sorted(dict_dtw.items(), key=lambda x:x[1][1])[:10]) print('\n似ていない都道府県トップ10(DTW)') display(sorted(dict_dtw.items(), key=lambda x:x[1][0], reverse=True)[:10]) print('\n似ていない都道府県トップ10(fastDTW)') display(sorted(dict_dtw.items(), key=lambda x:x[1][1], reverse=True)[:10])
似ている都道府県の組み合わせトップ10は以下の通り。tslearnとfastdtwで違いはあるものの、最も距離が近い組み合わせの神奈川と富山はtslearnとfastdtwで同じ。
似ていない都道府県の組み合わせトップ10は以下の通り。こちらもtslearnとfastdtwで違いはあるものの、最も距離が遠い組み合わせの岐阜と高知はtslearnとfastdtwで同じ。
最も距離が短い神奈川と富山のプロット。ほぼ一致している。
最も距離が遠い岐阜と高知のプロット。確かにけっこう違う。
tslearnとfastdtwそれぞれで距離が短いトップ5を比較。以下のコードを上記コードのあとに追加する。
(2021.12.16 グラフ作成部のコードを追加)
tslearn_top5 = sorted(dict_dtw.items(), key=lambda x:x[1][0])[:5] fastdtw_top5 = sorted(dict_dtw.items(), key=lambda x:x[1][1])[:5] for i, ((prefs1, values1), (prefs2, values2)) in enumerate(zip(tslearn_top5, fastdtw_top5)): fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 3)) df.loc[:, prefs1].plot(ax=axes[0]) df.loc[:, prefs2].plot(ax=axes[1]) plt.show()左がtslearnで右がfastdtw。どちらが良いのかは判断が難しい・・
最後のグラフの作り方についてもご教授いただけないでしょうか。
返信削除コメントを見落としていて返信遅くなりました。
削除グラフ作成箇所のコードを追記したのでご確認ください。