Python pandas プロット機能を使いこなす
pandas
は可視化のための API を提供しており、折れ線グラフ、棒グラフといった基本的なプロットを簡易な API で利用することができる。一般的な使い方は公式ドキュメントに記載がある。
これらの機能は matplotlib
に対する 薄い wrapper によって提供されている。ここでは pandas
側で一処理を加えることによって、ドキュメントに記載されているプロットより少し凝った出力を得る方法を書きたい。
補足 サンプルデータに対する見せ方として不適切なものがあるが、プロットの例ということでご容赦ください。
パッケージのインポート
import matplotlib.pyplot as plt plt.style.use('ggplot') import matplotlib as mpl mpl.__version__ # '1.5.0' import numpy as np np.__version__ # '1.10.1' import pandas as pd pd.__version__ # u'0.17.0'
折れ線グラフ、棒グラフ系
サンプルデータとして 気象庁から 東京、札幌、福岡の 2014 年の日別平均気温データをダウンロードし、pd.read_csv
で読み込んだ。
df = pd.read_csv('data.csv', index_col=0, header=[0, 1, 2], skiprows=[0], encoding='shift-jis') df = df.iloc[:, [0, 3, 6]] df.columns = [u'東京', u'札幌', u'福岡'] df.index = pd.to_datetime(df.index) df.head()
まずは単純な折れ線グラフを描く。
df.plot()
次に、適当な単位 (ここでは月次) でグルーピングして棒グラフを書きたい。集計には pd.Grouper
を利用する。
参考 Python pandas アクセサ / Grouperで少し高度なグルーピング/集計 - StatsFragments
monthly = df.groupby(pd.Grouper(level=0, freq='M')).mean() monthly
このとき、index
が 時系列 ( DatetimeIndex
) の場合、そのままでは x 軸がタイムスタンプとして表示されてしまう。
monthly.plot.bar(color=['#348ABD', '#7A68A6', '#A60628'])
x軸 を簡単にフォーマットしたい場合、Index.format()
メソッドを利用して index
を文字列表現に変換するとよい。
monthly.index.format() # ['2014-01-31', '2014-02-28', '2014-03-31', '2014-04-30', '2014-05-31', '2014-06-30', # '2014-07-31', '2014-08-31', '2014-09-30', '2014-10-31', '2014-11-30', '2014-12-31'] monthly.index = monthly.index.format() monthly.plot.bar(color=['#348ABD', '#7A68A6', '#A60628'])
また、各棒の塗り分けには colormap
を指定することもできる。
monthly.plot.bar(cmap='rainbow')
折れ線グラフ / 棒グラフを一つのプロットとして描画する場合は以下のようにする。.plot
メソッドは matplotlib.axes.Axes
インスタンスを返すため、続くプロットの描画先として その Axes
を指定すればよい。
ax = monthly[u'札幌'].plot(legend=True) monthly[[u'東京', u'福岡']].plot.bar(ax=ax, rot=30)
また、matplotlib
側で 極座標の Axes
を作成しておけば、レーダーチャートのような描画もできる。
補足 一部 線が切れているのは負値のため。
fig = plt.figure() ax = fig.add_axes([0.1, 0.1, 0.9, 0.9], polar=True) indexer = np.arange(1, 13) * 2 * np.pi / 12 monthly.index = indexer monthly.append(monthly.iloc[0]).plot(ax=ax) ax.set_xticks(indexer) ax.set_xticklabels(np.arange(1, 13));
分布描画系
各都市の気温の分布が見たい、といった場合にはヒストグラムを描画する。
df.plot.hist(bins=100, alpha=0.5)
より細かい単位でグループ分けしてグラフを描きたい場合は、まず plt.subplots
で必要な Axes
を生成する。続けて、pandas
でグループ化したデータを各 Axes
に対して描画すればよい。
ここでは月ごとに サブプロットにして カーネル密度推定したグラフを描画してみる。
fig, axes = plt.subplots(4, 3, figsize=(8, 6)) plt.subplots_adjust(wspace=0.5, hspace=0.5) for (ax, (key, group)) in zip(axes.flatten(), df.groupby(pd.Grouper(level=0, freq='M'))): ax = group.plot.kde(ax=ax, legend=False, fontsize=8) ax.set_ylabel('') ax.set_title(key, fontsize=8)
同様に箱ヒゲ図も描ける。
fig, axes = plt.subplots(4, 3, figsize=(8, 6)) plt.subplots_adjust(wspace=0.5, hspace=0.5) for (ax, (key, group)) in zip(axes.flatten(), df.groupby(pd.Grouper(level=0, freq='M'))): ax = group.plot.box(ax=ax) ax.set_ylabel('') ax.set_title(key, fontsize=8)
散布図系
通常の散布図は以下のようにして描ける。
df.plot(kind='scatter', x=u'札幌', y=u'福岡')
各点を適当に色分けしたい場合、c
キーワードで各点の色を指定する。また、colormap
も合わせて指定できる。ここで指定した値は連続値として扱われるため colorbar
が表示されている (非表示にすることもできる)。
df.plot(kind='scatter', x=u'札幌', y=u'福岡', c=df.index.month, cmap='winter')
各点をグループ別に塗り分ける ( 離散値として扱う ) 場合は、単一の Axes
に対して グループ化したデータを順番に描画していけばよい。
cmap = plt.get_cmap('rainbow') colors = [cmap(c / 12.0) for c in np.arange(1, 13)] colors # [(0.33529411764705885, 0.25584277759443558, 0.99164469551074275, 1.0), # (0.17058823529411765, 0.49465584339977881, 0.96671840426918743, 1.0), # ... # (1.0, 0.25584277759443586, 0.12899921653020341, 1.0), # (1.0, 1.2246467991473532e-16, 6.123233995736766e-17, 1.0)] fig, ax = plt.subplots(1, 1) for i, (key, group) in enumerate(df.groupby(pd.Grouper(level=0, freq='M')), start=1): group.plot(kind='scatter', x=u'札幌', y=u'福岡', color=cmap(i / 12.0), ax=ax, label=i)
また、ダミーのカラムを作成することで月次の気温の分布を散布図としてみることもできる。
df['month'] = df.index.month df.plot(kind='scatter', x='month', y=u'札幌')
x 軸方向に散らす。
df['month2'] = df.index.month + np.random.normal(loc=0, scale=0.05, size=len(df.index.month)) df.plot(kind='scatter', x='month2', y=u'札幌')
バブルチャートも描ける。前処理として札幌の気温を離散化し、月次のデータ数を集計する。
df2 = df.copy() df2[u'札幌2'] = df2[u'札幌'] // 10 * 10 df2['count'] = 1 df2 = df2.groupby(['month', u'札幌2'])['count'].count().reset_index() df2.head()
バブルの大きさは s
キーワードで指定する。
df2.plot.scatter(x='month', y=u'札幌2', s=df2['count'] * 10) df.plot(kind='scatter', x='month2', y=u'札幌')
さらに変形して plt.imshow
でヒートマップを描画する。imshow
は pandas
の API にはないため、DataFrame.pipe
でデータを渡す。
piv = pd.pivot_table(df, index=u'札幌2', columns=df.index.month, values=u'札幌', aggfunc='count') piv = piv.fillna(0) piv
piv.pipe(plt.imshow, cmap='winter') ax = plt.gca() ax.invert_yaxis() ax.set_yticks(np.arange(4)) ax.set_yticklabels(piv.index);
まとめ
pandas
での前処理 + 可視化機能の組み合わせを利用して、より柔軟にプロットを行う方法を記載した。pandas
の裏側は ndarray
のため、最後の例のように pandas
側に API がないプロットも簡単に描ける。
Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理
- 作者: Wes McKinney,小林儀匡,鈴木宏尚,瀬戸山雅人,滝口開資,野上大介
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/12/26
- メディア: 大型本
- この商品を含むブログ (11件) を見る