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)
ボリュームゾーンや分布の形など、大まかな傾向だけ見られれば十分な場合、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)))
年齢を5歳区切りにする場合など、自分で設定した階級に分割したい場合はplt.hist()
を使うのが楽です。
plt.hist()
の第2引数に階級の区切りのリストを渡すとその階級で分割してくれます。
データに欠損値が含まれてはいけないので、dropna()
を行う必要がある点に注意が必要です。
追記
pd.Series.hist(bins=range(0, 101, 5))
のようにbinsに区切りを渡すと同様のことが出来るようです!
参考になる記事をありがとうございます。ところで、pandasでもdf.plot.hist(bins=range(0,100,5))など指定すれば任意の位置でbinを切れますが、これは紹介されているplt.hist()を使う方法の代替とならないでしょうか? https://t.co/JOnOTFbQ3b
— Ken Kuroki (@enuroi) May 30, 2018
@enuroiさん、ありがとうございました!
区間を軸に明示したい場合
pd.cut(data.Age, list(range(0, 101, 5)), right=False).value_counts().sort_index().plot.bar(color='gray')
pd.cut()
を使うと各データに対して、階級のどこに所属しているかを返してくれます。
その結果をvalue_count()
を用いてカウントし、ソートして棒グラフにしています。
この方法を使うメリットは、軸に区間が明示されることです。 整数値を分割した場合、左端・右端のどちらを含んでどちらを含んでいないのかが重要になることがあります。
pd.cut()
のオプションでright=False
のときは左端を含み、右端を含まないようにします。逆にright=True
にすれば左端を含まず、右端を含むように集計できます。
まとめ
- pd.Series.plot.hist()
- plt.hist()
- pd.cut().value_counts().sort_index().plot.bar()
の3種類のヒストグラムプロット方法を紹介しました。
今回のコードはGitHubに置いてあります。
いじょ。