天色グラフィティ

技術ちっくなことを書きます

pandas + matplotlibで描くヒストグラムいろいろ

データ解析コンペの初期段階では、データを可視化して眺め、特徴を探すという探索的データ分析(EDA)が行われます。

Pythonでデータ分析している場合、可視化にはpandasのプロット機能、もしくはmatplotlibを使うことが多いでしょう。 今回はヒストグラムに絞って、僕が良く使っている書き方を紹介したいと思います。

題材とするデータにはKaggleのTitanicコンペのデータを使うことにしましょう。一部を抜き出してくるとこんな感じのデータになっています。今回はこのAgeの列を可視化してみたいと思います。

data = pd.read_csv('input/train.csv')
data[['Name', 'Age']].head()
Name Age
0 Braund, Mr. Owen Harris 22.0
1 Cumings, Mrs. John Bradley (Florence Briggs Th... 38.0
2 Heikkinen, Miss. Laina 26.0
3 Futrelle, Mrs. Jacques Heath (Lily May Peel) 35.0
4 Allen, Mr. William Henry 35.0

大まかな傾向だけ見られれば良い場合

data.Age.plot.hist(bins=20, color='gray', rwidth=.8)

f:id:ejinote:20180423110247p:plain

ボリュームゾーンや分布の形など、大まかな傾向だけ見られれば十分な場合、pd.Seriesに対してplot.hist()メソッドを呼び出すのをよく使います。 pd.Series.plotを介してプロットを行うメリットとしては、

  • 欠損値をスルーしてくれる
  • ラベルなどをいい感じに付けてくれる

などがあります。

rwidthを指定するとそれぞれのバーの幅を調節することができます。0.8くらいを指定しておくと見やすくなるのでオススメです。

デメリットは階級の境界が指定できない上、プロット上も分かりにくいことです。

自分で設定した階級で分割したい場合

plt.hist(data.Age.dropna(), list(range(0, 101, 5)), color='gray', rwidth=.8)
plt.xticks(list(range(0, 101, 10)))

f:id:ejinote:20180423105745p:plain

年齢を5歳区切りにする場合など、自分で設定した階級に分割したい場合はplt.hist()を使うのが楽です。

plt.hist()の第2引数に階級の区切りのリストを渡すとその階級で分割してくれます。 データに欠損値が含まれてはいけないので、dropna()を行う必要がある点に注意が必要です。

追記

pd.Series.hist(bins=range(0, 101, 5)) のようにbinsに区切りを渡すと同様のことが出来るようです!

@enuroiさん、ありがとうございました!

区間を軸に明示したい場合

pd.cut(data.Age, list(range(0, 101, 5)), right=False).value_counts().sort_index().plot.bar(color='gray')

f:id:ejinote:20180423105748p:plain

pd.cut()を使うと各データに対して、階級のどこに所属しているかを返してくれます。 その結果をvalue_count()を用いてカウントし、ソートして棒グラフにしています。

この方法を使うメリットは、 x軸に区間が明示されることです。 整数値を分割した場合、左端・右端のどちらを含んでどちらを含んでいないのかが重要になることがあります。

pd.cut()のオプションでright=Falseのときは左端を含み、右端を含まないようにします。逆にright=Trueにすれば左端を含まず、右端を含むように集計できます。

まとめ

  • pd.Series.plot.hist()
  • plt.hist()
  • pd.cut().value_counts().sort_index().plot.bar()

の3種類のヒストグラムプロット方法を紹介しました。

今回のコードはGitHubに置いてあります。

github.com

いじょ。