時系列データに使える可視化のテクニック(Python)

こんにちは。大学院を少しお休みしてインドのITスタートアップでデータサイエンスのインターンをしているMasanori(Masanori_724)です。

インターンをしている企業はインド系の企業で日本人はおらず、また、インドに来て1週間経ちましたが未だに僕の住む街では日本人に出会ったことはありません。そんな環境でデータサイエンティストを目指して奮闘中です。

インターンではPM2.5の値の時系列解析に取り組んでいます。そのため、時系列解析についてよく調べているのですが、モデルの理論やコーディングの話は多いですがデータの可視化についてはあまり触れられていない印象でした。

 しかし、僕は統計が専門ということもあって、ただデータを解析するだけでなくデータの分布をしっかり眺め理解することはデータ解析では重要なことだと感じています。

そこで今回はPythonでの時系列解析におけるデータの可視化方法をまとめてみました。

利用するデータ

今回扱うデータはRの組み込みデータとして有名なAirPassengers(飛行機乗客数)を利用します。こちらからダウンロードをしてください。

データは月ごとの飛行機の乗客数データで、期間は1949年1月から1960年12月までです。データの詳細は以下のリンクから確認できます。

stat.ethz.ch

まずはじめに、必要なモジュールをまとめてインポートしておきます。

import pandas as pd
import matplotlib.pyplot as plt
import datetime
import statsmodels.api as sm
from pandas.plotting import autocorrelation_plot
from pandas.plotting import lag_plot
from matplotlib.pylab import rcParams
rcParams['figure.figsize'] = 16,9

データの最初の5行のみ記載しておきます。

df = pd.read_csv("AirPassengers.csv")
df.head()

f:id:nori0724:20190925070343p:plain

#pandas.Seriesに変換
series = pd.Series(df['#Passengers'], dtype='float') 
series.index = pd.to_datetime(df['Month']) 

以上で準備ができたので、可視化に入ります。

時系列折れ線グラフ

まずは時系列折れ線グラフです。x軸は時間(月)、y軸は乗客数です。時系列折れ線グラフではデータを直接可視化できます。

plt.ylabel("Passengers")
series.plot()
plt.show()

f:id:nori0724:20190925072247p:plain

時系列折れ線グラフ

以下のように書くことによって点で表現することもできます。

plt.ylabel('Passengers')
series.plot(style='k.') plt.show()

f:id:nori0724:20190925073302p:plain

今回扱っているデータセットは12年間のデータがあります。そこで、年ごとにデータをグループ化し、年ごとに折れ線グラフを作成することもできます。 

groups = series.groupby(pd.Grouper(freq='A'))
years = pd.DataFrame()
for name, group in groups:
    years[name.year] = group.values
years.plot(subplots=True , legend=True)
plt.xlabel("Month")
plt.show()

f:id:nori0724:20190925074706p:plain

上記のグラフの場合、年ごとに乗客数の大小を比較するのではなく、年ごとの折れ線グラフの概形を知ることが目的と言えそうです。また同年での月ごとの乗客数の大小の比較はできそうです。どの年を見ても夏場に乗客数が増え冬場に乗客数が減るという傾向がありそうです。(y軸の範囲は年ごとに異なっているので注意が必要です。)

以下のように一つのプロットエリアで年ごとの折れ線グラフを書くことも可能です。

groups = series.groupby(pd.Grouper(freq='A'))
years = pd.DataFrame()
for name, group in groups:
    years[name.year] = group.values
years.plot(legend=True)
plt.xlabel("Month")
plt.ylabel("Passengers")
plt.show()

f:id:nori0724:20190925075457p:plain

このグラフだと同月の乗客数の年ごとの大小比較ができそうです。

ヒストグラム

次はヒストグラムです。日付の順序に関係なくデータの分布を見ることができます。右に裾が長い分布となっています。(binsの調整が難しい...)

plt.xlabel("passengers")
plt.ylabel("frequency")
series.hist(bins=15)
plt.show()

 

f:id:nori0724:20190925192132p:plain

密度plot

密度plotにすると観測値の分布の形状をよりよく把握できますが、この辺はまだまだ勉強が必要です。。。

series.plot(kind='kde')
plt.show()

f:id:nori0724:20190925192530p:plain

箱ひげ図

次は箱ひげ図です。年ごとの最大値・最小値・中央値・四分位数を読み取ることができます。

groups = series.groupby(pd.Grouper(freq='A'))
years = pd.DataFrame()
for name, group in groups:
    years[name.year] = group.values
years.boxplot()
plt.xlabel("Month")
plt.ylabel("Passengers")
plt.show()

f:id:nori0724:20190925193918p:plain

ヒートマップ

続いてヒートマップです。x軸は月、y軸は年を表しています。また、カラーバーが示すように明るい色ほど乗客数が高く、暗い色ほど乗客数が少ないことを示しています。このことからも夏に乗客数が多いこと、年々乗客数が増えていることがわかります。トレンドや季節性がもっと複雑なものだと読み取りが面白くなりそうです。

groups = series.groupby(pd.Grouper(freq='A'))
years = pd.DataFrame()
for name, group in groups:
    years[name.year] = group.values
years = years.T
plt.matshow(years, interpolation=None, aspect='auto')
plt.xlabel("Month")
plt.ylabel("Year")
plt.colorbar()
plt.show()

f:id:nori0724:20190925200619p:plain

散布図

最後はラグplotです。t時点の乗客数とt+1時点の乗客数との相関関係を読み取ることができます。グラフからわかるように強い正の相関があることが見てわかります。

from pandas.plotting import lag_plot
lag_plot(series)
plt.show()

f:id:nori0724:20190925203551p:plain

また1時点先だけでなく、自分が指定した時点(例えばt+1時点 vs t-6時点)の散布図をplotすることもできます。時点が離れるほど広がりが大きくなり相関が弱くなっていることがわかります。

values = pd.DataFrame(series.values)
lags = 6
columns = [values]
for i in range(1,(lags + 1)):
    columns.append(values.shift(i))
dataframe = pd.concat(columns, axis=1)
columns = ['t+1']
for i in range(1,(lags + 1)):
    columns.append('t-' + str(i))
dataframe.columns = columns
plt.figure(1)
for i in range(1,(lags + 1)):
    ax = plt.subplot(240 + i)
    ax.set_title('t+1 vs t-' + str(i))
    plt.scatter(x=dataframe['t+1'].values, y=dataframe['t-'+str(i)].values)
plt.show()

f:id:nori0724:20190925203855p:plain

 

以上が時系列データで使える可視化のテクニックでした。他にも使えそうなplotが見つかった場合には随時追加していきます。グラフからの考察にはそこまで時間をかけていないので、間違い等あればコメントください。

参考資料

momonoki2017.blogspot.com

machinelearningmastery.com

pandas.pydata.org

pandas.pydata.org