こんにちは,米国データサイエンティストのかめ(@usdatascientist)です.
データサイエンスのためのPython入門第25回です(講座の目次はこちら).今回は前回紹介したSeabornを使って,Categorical Plotと呼ばれる図(barplotやboxplotなど)をplotしていきます.
(「データサイエンスのためのPython講座」動画版がでました!詳細はこちら)
前回紹介したdistplotやpairplotほど頻度は高くないと思いますが,論文やお客様・社内への報告書などにはよく使える図なので覚えておきましょう.
また,boxplot(箱ひげ図)については第23回にも紹介しているので参考にしてください.
Categorical Plotがどういう図かわからない!っていう人,この記事を読み進めればなんとなくわかってきます.あと,「Categorical Plot」っていう名前は多分Seaborn特有の言い方な気がするので,仕事で使う用語ではないです.逆に,「barplot」とか「boxplot」とかはめちゃくちゃ出てきます.
今回紹介するのは
- sns.barplot()
- sns.countplot()
- sns.boxplot()
- sns.violinplot()
- sns.swarmplot()
です.よく使うのはboxplotとswarmplotです.特に私はswarmplotが好きです.データ数にもよりますが,そこまでデータ数が多くない場合はswarmplotで分布をみるようにしています.特にこの二つを覚える意識で読み進めてください.
目次
いわゆる「棒グラフ」を作るsns.barplot()
いわゆる「棒グラフ」を作れます.カテゴリーごとに分けて,(デフォルトでは)指定したカラムの平均値を比較することができます.
第15回にて,groupbyでグループ別(カテゴリ別)の各カラムの統計量をみましたが,実際に誰かに統計量を見せる時は基本グラフを見せます.これは重要なことなので覚えておきましょう.
「なにかの数字を比べる際には必ずグラフを使って説明する」は,データサイエンスの鉄則です.このbarplotはその基本となるplotなのです.
さて,今回も今までと同様タイタニックデータを使っていきます.(タイタニックデータについては第11回を参照ください)
1 2 3 4 5 6 |
import pandas as pd import seaborn as sns %matplotlib inline df = pd.read_csv('train.csv') df.head() |
今回は試しに,Survivedをカテゴリーに指定して,Ageの平均を棒グラフ(barplot)で比べてみましょう.(何度か過去の記事で出てきてます)
使い方は簡単で,sns.barplot()に,x引数にカテゴリーのカラム,y引数に比較対象のカラム, data引数にDataFrameを入れるだけ!
1 |
sns.barplot(x='Survived', y='Age', data=df) |
横軸にSurvived,縦軸にAgeがきていて,それぞれの平均値が棒グラフで比較できるようになっています.黒い線が引かれているのはError Barと呼ばれるもので,不確かさを示すものです.
今回の「平均値」というのはあくまでもタイタニックデータのtrain.csvという「ある母集団(=全乗客)に対しての標本(=train.csv)を取った際の平均値」であり,全乗客の平均値ではないです.が,統計的に「全乗客の平均値はだいたいこの辺に含まれるよ」というのがわかります.その範囲を示すのがErrror Barだと思ってください.
Error Barを示すには,標準偏差をつかったり,標準誤差や任意の信頼区間を使うことが多いです.(標準偏差については第9回で触れています.)
標準誤差や信頼区間について今はわからなくてOKです.今回はあくまでもSeabornの使い方の説明であって統計学についての講座ではないので,そのあたりは統計学講座で別途扱います.
追記)信頼区間についての記事を書きました.詳しくはこちらをご参照ください!
Seabornではデフォルトで95%信頼区間がError Barになっています.感覚的にいうと,「正規分布の母集団に対して100回ランダムにデータを抽出してその平均から95%信頼区間を求めたら,95回はその区間に母集団の平均が含まれる」というのを統計的に裏付けているものだとおもえばOKです.
(なにを言ってるかわからない方,統計学講座でやるので心配しなくてOKです.)
また,この二つの平均値に対して「本当に差があるのか?」「たまたま標本データがそういうデータなのでは?」(これを統計的有意性という)という疑問に対しても,この信頼区間というのが関わってきます.なので,統計がわかる人が上のbarplotを見れば,統計的有意性(今後統計学講座でやります)を示されなくてもError Barを見れば有意性の有無は大体わかります.
SeabornでこのError Barの信頼区間(Confidence Intervals)を変えたい,または標準偏差を使いたい場合はci引数を使います.興味がある人はリファレンスを確認してください.
また,平均値以外の値を比較したい場合estimator引数を使います.これには,aggregate function(第15回でも触れました)を使いますが,NumPyの関数でだいたい事足りるので,それ以上の深追いは不要だと思います.
例えば平均じゃなくて中央値を比べたかったら
1 2 |
import numpy as np sns.barplot(x='Survived', y='Age', data=df, estimator=np.median) |
こんな感じでestimatorにnp.median関数を入れればOK.
んーこれは面白い,中央値を比較すると有意差が無いように見えますね.
この謎は前回pairplotで出したhue=’Survived’のAgeのヒストグラムを見るとわかるかもしれません.
一つの統計量だけを比べると,ミスリーディングが起きるいい例ですね.
データ数を比較するsns.countplot()
棒グラフというとどちらかとこちらのイメージの人が多いと思います.単純にデータ数をカテゴリ別に比べます.
sns.countplot()関数にカテゴリーとするカラム名を引数xに入れます.hue引数を使うことでさらに区分けできます.
1 |
sns.countplot(x='Sex', data=df, hue='Survived') |
単純にデータ数を表すグラフですが,割と使います.
例えばStudyの最初にデータ数を必ず明記しますが,このcountplotを使って「〇〇というデータをXX数使いました.」みたいに言えます.
カテゴリ別に値を比較するsns.boxplot()
barplotよりも実際よく使うのがこのsns.boxplot()です.第23回で紹介した箱ひげ図と同じですが,Seabornの方が使い勝手がいいし綺麗なのでこちらをよく使います.
では,試しにタイタニックデータでPclassごとのAgeの分布をboxplotしてみましょう.使い方は先ほどのbarplotと同じです.
1 |
sns.boxplot(x='Pclass', y='Age', data=df) |
か,簡単すぎる・・・
Seaborn素晴らしくないですか?
もうこれだけでお客さんに持っていけますよ.Excelでグラフ作ってたのがあほらしいですよね.
hue引数をつけることで,それぞれのカテゴリ内をさらに区分けしてくれます.
1 |
sns.boxplot(x='Pclass', y='Age', data=df, hue='Survived') |
美しいですね.
ただ,Seabornでグラフを作ってると簡単に生成できるがゆえに複雑になってしまうので注意です.
あくまでもグラフは「見せるもの」でありわかりやすい必要があります.「そのグラフで何を説明するか」が重要です.
私だったらこのグラフでは「チケットのクラスが上がる(1st→3rd)につれて年齢層が上がっており,同クラス内では生存者の方が年齢が低い傾向がある」と説明します.(もちろん,厳密にいうには統計的に有意であることを証明する必要はありますが)
逆にいうと,それを説明するためにこのグラフを作るイメージですね.
boxplotだけでもいいんですが,boxplotだと実際の分布がわからないんですよね・・・
そこでおすすめなのがviolinplotやswarmplotです.violinplotは結構メジャーなので覚えた方がいいのと,個人的にはswarmplotがわかりやすくて好きです.
データの分布を可視化できるsns.violinplot()
使い方はboxplot()と同じです.boxplotだと,データの分布がどうなっているのかわからないですが,violinplotはデータの分布に応じて箱の形が変わります.
大抵のデータでは平均にデータが集まる(正規分布など)ので結果バイオリンのような形をするのでviolinplotと呼びます.
1 |
sns.violinplot(x='Pclass', y='Age', data=df) |
情報量が増えるので,若干ビジーなのと見たことない人からすると見方がわからないので注意です.
「なにを伝えたいか」によって使うグラフを変えましょう.もし統計量の比較だけを伝えたいなら先ほどのboxplotで事足りるし,Ageの分布をちゃんと説明したい場合(例えば1stクラスはAgeが全体に分布しているが,2ndと3rdはやたら平均に偏ってるとか)はviolinplotがいいかもしれません.
boxplotだけではわからない情報がみえるので面白いです.2ndと3rdは分布の形が似てますね.
boxplot同様,hue引数を指定することも可能です.やってみてください.
本当の分布を確認できるsns.swarmplot()
実は先ほどのviolinplotって,標準化された形なんです.第15回でやった通り,1stクラス2ndクラスに比べ3rdクラスの乗客の方が圧倒的に多いです.
しかし,violinplotを見ると乗客数の差がそれぞれのPclassの幅の差に反映されていません.
これはviolinplotで表示しているのはあくまでも密度であり実際の数の大きさではないからです.
なので,例えば2ndクラスの30才の幅と3ndクラスの22才あたりの幅を比較しても数の比較はできません.
sns.swarmplot()を使うと,実際の分布を見ることができます.これ,すごく便利です.使い方はboxplot, violinplotと同じです.
1 |
sns.swarmplot(x='Pclass', y='Age', data=df) |
散布図をカテゴリーごとにplotした感じですね.
これを見れば実際の分布をカテゴリーごとに見ることができます.統計量はでてこないのでboxplotやviolinplotと合わせて使うといいかもしれません.
また,データ数が多すぎるとみにくくなるので注意です.多すぎて潰れちゃってる(今回だと3rdクラス)場合はsize引数でmarkerのサイズを小さくしましょう.
1 |
sns.swarmplot(x='Pclass', y='Age', data=df, size=4) |
これをみると各クラスの利用層に仮説が立てられますね.2nd, 3rdクラスは小さい子がいる家族が多く,1stクラスは年配の方が多そうです.
boxplot同様hue引数を指定すれば,markerを色分けすることもできます.
1 |
sns.swarmplot(x='Pclass', y='Age', data=df, size=4, hue='Survived') |
3rdクラスの圧倒的死亡率ww
まぁこんなこともグラフから直感的にわかってしまうのです.
個人的にはこのswarmplotがすごく好きです.あまり統計量でなにかを語るのは好きではなく,実際の分布を見る方が安心できます.
もちろんデータ数が多くなるとこうもいかないので注意ですが,データ数が数百オーダーであれば使えると思います.
まとめ
今回はカテゴリーごとに分布を見せるCategorical Plotを紹介しました.
紹介したのは以下の5つです.↓
特にboxplotとswarmplotを組み合わせると非常にGoodだと思います.
boxplotで統計量を見せ→swarmplotで実際の分布を見せるイメージですね.
Seabornは本当に簡単にグラフを作れてしまう反面,簡単にビジーな図になってしまいます.
「そのグラフで何を伝えたいのか」が一番重要で,それを伝えるために最低限必要な情報のみグラフに入れるようにするといいと思います.
それでは!
追記)次回書きました.次回はSeabornを使って美しいHeatmapを描画します.データサイエンスではめちゃくちゃ使いますので使えるようにしましょう.
[…] データサイエンスのためのPython入門第25回書きました Seabornを使ってboxplotとか,violinplotとかswarmplotを作ります これらの単語知らない人は是非見てみてください.たった一行で素晴らしく綺麗なグラフが描けちゃいます. ね?もうExcel使ってるのアホらしいでしょw datawokagaku.com/seaborn_catego… […]