以前に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。どちらが良いのかは判断が難しい・・




最後のグラフの作り方についてもご教授いただけないでしょうか。
返信削除コメントを見落としていて返信遅くなりました。
削除グラフ作成箇所のコードを追記したのでご確認ください。