Python
pandas
seaborn

ズレた時系列データのヒートマップを上下に並べる。seabornで。

目的

  • x軸方向(時間方向)にずれたデータを1つのヒートマップ上に並べて表示したい.
  • そのために,データの整形を行う.

状況

  • 複数のセンサからデータをサンプリング
  • サンプリング周期は同じ
  • 取得タイミングがずれている
  • データ数が異なる

Ex.) 分散システムになっていて,それぞれのデータが中央に送られてくる.

ので,一筋縄ではいきません.

データ整形からプロットまで

データの読み込み(作成)

pd.read_csv() とかで読むけど,今回はダミーデータを使用します.

# 時間のズレを作る
time_A = np.arange(5, step=0.01)
time_B = np.arange(5.1, step=0.01)

# 適当にばらつかせる
time_A += list(map(int, np.random.normal(scale=0.01, size=len(time_A))))
time_B += list(map(int, np.random.normal(scale=0.01, size=len(time_B))))

# 取得データ
data_A = np.sin(2*np.pi*time_A)
data_B = np.cos(2*np.pi*time_B)

# dataframeにまとめる
df_A =  pd.DataFrame({"time": time_A, "value": data_A}) 
df_B =  pd.DataFrame({"time": time_B, "value": data_B}) 

このときのdf_Xがサンプリングしたデータが纏められたDataFrameです.
行数はサンプリング数,列はその系統のデータ数+1(time)になります.

それぞれのデータをマージする

# 時間をマージして並べ替え

time = pd.concat([df_A["time"], df_B["time"]])
time = time.sort_values().reset_index(drop=True)

# tmp
new_data_A = []
new_data_B = []

# データが存在する場合はそのデータを,ない場合はNaNを突っ込んでおく
# for使わずにもっときれいにできそう
for i in time:
    new_data_A.append(df_A[df_A.time == i].value.values[0] if i in df_A.time.values else np.NaN)
    new_data_B.append(df_B[df_B.time == i].value.values[0] if i in df_B.time.values else np.NaN)

# 補完する
series_A = pd.Series(new_data_A)
series_B = pd.Series(new_data_B)

series_A = series_A.interpolate()
series_B = series_B.interpolate()

両方のデータを1つにまとめてしまいます.
任意のタイミングで両方同時にサンプリングされていることは保証されないことが前提条件になるので,足りないデータは補完しています.

この処理で,両方のデータは同じ軸上に並べることができるようになりました.

プロットする

プロット用のDataFrameを作成,プロットします.

df = pd.DataFrame(data=[series_A.values, series_B.values], columns=time)
sns.heatmap(df, cmap=sns.color_palette("Blues", 24))

image.png

おわりに

ということで,2つのサイズやタイミングが異なる,しかしながら同じ軸で見たいデータをヒートマップで描くことが出来ました.
分散型のシステムなんかだとこういうこと結構あるんじゃないでしょうか.

残された問題

  • x軸方向は等間隔で分割されるので,サンプリング周期がぶれるとズレる.
  • forを回してるところ,pandasの機能をうまく使えばシンプルにかけそう(優先度低)