プロットを始める前にデータを調べるのは常に良い考えです。 1160>
import pandas as pd# Read in data and examine first 10 rows
flights = pd.read_csv('data/formatted_flights.csv')
flights.head(10)
The flight arrival delays are in minutes and negative values mean the flight was early (it turns out often tend to arrive early, just never when we’re on them!) フライトの到着遅延は分で表示し、負の値は早く到着したことを示します。 30万以上のフライトがあり、最小の遅延は-60分、最大の遅延は120分です。 データフレーム内の他の列は、比較に使用できる航空会社の名前です。
1 つの変数の調査を開始する素晴らしい方法は、ヒストグラムを使用することです。 ヒストグラムは、変数をビンに分割し、各ビン内のデータ ポイントをカウントし、ビンを X 軸に、カウントを Y 軸に表示します。 私たちのケースでは、ビンはフライトの遅延を表す時間間隔になり、カウントはその間隔に入るフライトの数になります。 binwidthはヒストグラムの最も重要なパラメータで、常にbinwidthのいくつかの異なる値を試して、データに最適なものを選択する必要があります。
Pythonで基本的なヒストグラムを作成するには、matplotlibまたはseabornを使用することができます。 以下のコードは、同等の図を作成する両ライブラリの関数呼び出しを示しています。 plotの呼び出しでは、binwidthをbinの数で指定します。 このプロットでは、5分の長さのビンを使用します。つまり、ビンの数はデータの範囲(-60分から120分まで)をbinwidthで割った5分(bins = int(180/5)
)となります。
For most basic histograms, 私なら matplotlib のコードの方がシンプルなのでそちらにしますが、後ほど seaborn distplot
の関数を使ってさまざまな分布を作成するので、さまざまなオプションに慣れておくとよいでしょう。
なぜbinwidthを5分としたのか? 最適なビン幅を把握する唯一の方法は、複数の値を試してみることです! 以下は、matplotlibでbinwidthの幅を変えて同じ図を作るコードです。 最終的には、ビン幅に正解も不正解もありませんが、分布を最もよく表していると思うので5分を選びました。
ビン幅を選択すると結果のプロットに大きく影響します。 小さいビン幅はプロットを乱雑にしますが、大きいビン幅はデータのニュアンスを不明瞭にするかもしれません。 Matplotlibは自動的に適切なbinwidthを選んでくれますが、私はいくつかの値を試した後にbinwidthを自分で指定するのが好きです。 いくつかのオプションを試して、特定のデータに最適なものを見てください。
When Histograms Fail
Histograms are a great way to start exploring a single variable drawn from one category. しかし、複数のカテゴリにわたって 1 つの変数の分布を比較したい場合、ヒストグラムは読みやすさの点で問題があります。 たとえば、航空会社間の到着遅延の分布を比較したい場合、うまくいかないアプローチは、同じプロット上に各航空会社のヒストグラムを作成することです。
(Note that the y-axis has been normalized to account for the different of flights between airlines.” (航空会社間で異なる便数を考慮して、Y軸を正規化していることに注意してください。 これを行うには、sns.distplot
関数呼び出しに引数norm_hist = True
を渡します。)
このプロットはあまり有益ではありません! 重なり合ったすべての棒グラフは、航空会社間の比較をほとんど不可能にしています。 この一般的な問題に対するいくつかの可能な解決策を見てみましょう。
Solution #1: Side-by-Side Histograms
航空会社のヒストグラムを重ねる代わりに、横に並べて配置することが可能です。 これを行うには、各航空会社の到着遅延のリストを作成し、これをリストのリストとして plt.hist
関数呼び出しに渡します。 航空会社ごとに異なる色を指定し、見分けがつくようにラベルを付ける必要があります。 各航空会社のリストの作成を含むコードは以下の通りです:
デフォルトでは、リストのリストを渡すと matplotlib はバーを横に並べて配置します。 ここでは、そうしないとプロットが乱雑になりすぎるので、binwidthを15分に変更しましたが、この修正でも、これは効果的な図ではありません。 一度に処理する情報が多すぎるし、棒グラフとラベルの位置がずれているし、航空会社間の分布を比較するのはまだ難しいです。 プロットするときには、できるだけ見る人にわかりやすいようにしたいものです。 もう一つの解決策を見てみましょう。
Solution #2: Stacked Bars
各航空会社のバーを横に並べてプロットする代わりに、パラメータ stacked = True
をヒストグラム呼び出しに渡すことで、それらを重ねることができます:
# Stacked histogram with multiple airlines
plt.hist(, bins = int(180/15), stacked=True,
normed=True, color = colors, label=names)
さて、これは確かに良くありませんね! ここでは、各航空会社がビンごとに全体の断面として表現されていますが、比較することはほぼ不可能です。 たとえば、遅延が-15分から0分のとき、ユナイテッド航空とジェットブルー航空では、バーの大きさが違うのでしょうか? 私にはわからないし、視聴者もわからないでしょう。 積み上げ棒は解釈が難しいので、私は一般的に積み上げ棒の支持者ではありません(比率を視覚化する場合などのユースケースはありますが)。 1160>
Density Plots
最初に、密度プロットとは何でしょうか。 密度プロットはデータから推定されたヒストグラムを平滑化し、連続化したものです。 最も一般的な推定方法は、カーネル密度推定として知られています。 この方法では、連続した曲線(カーネル)を個々のデータ点に描き、これらの曲線をすべて足し合わせて一つの滑らかな密度推定を行います。 最もよく使われるカーネルはガウシアン(各データポイントでガウシアンベルカーブを生成する)である。 私のように、この説明が少しわかりにくい場合は、次のプロットを見てください。
ここで、x軸のそれぞれの小さな黒い垂直線がデータ点を表します。 個々のカーネル(この例ではガウシアン)は、各ポイントの上に赤い破線で描かれて表示されています。
x軸はヒストグラムと同じように変数の値ですが、y軸はいったい何を表しているのでしょうか。 密度プロットのY軸は、カーネル密度推定における確率密度関数です。 ただし、これは確率密度であって、確率ではないことに注意が必要です。 その違いは、確率密度はx軸の単位あたりの確率であることです。 実際の確率に変換するためには、x軸上の特定の区間に対する曲線下面積を求める必要がある。 少し混乱するのは、これは確率ではなく、確率密度なので、y軸は1より大きな値を取ることができることです。 密度プロットの唯一の要件は、曲線の下の総面積が1に積分することです。 私は一般に、密度プロットのy軸は異なるカテゴリ間の相対比較のためだけの値と考える傾向があります。
Density Plots in Seaborn
seabornで密度プロットを作成するには、distplot
またはkdeplot
関数を使用することができます。 1回の関数呼び出しで複数の分布を作ることができるので、私はこれからもdistplot
関数を使うことにします。 例えば、対応するヒストグラムの上にすべての到着遅延を表示する密度プロットを作ることができます:
# Density Plot and Histogram of all arrival delays
sns.distplot(flights, hist=True, kde=True,
bins=int(180/5), color = 'darkblue',
hist_kws={'edgecolor':'black'},
kde_kws={'linewidth': 4})
Finally, we have arrived at a effective solution ! 密度プロットを使うと、プロットが乱雑にならないので、航空会社間の比較が簡単にできます。 さて、ついに私たちが望むプロットができましたので、これらの航空会社はすべて、ほぼ同じ到着遅延分布を持っているという結論に達しました! しかし、データセットには他の航空会社もあり、密度プロットのもう1つのオプション・パラメータであるグラフの陰影を説明するために、少し異なる1つをプロットすることができます。 これは常に良い方法というわけではありませんが、分布間の違いを強調するのに役立つことがあります。 密度プロットに陰影をつけるには、distplot
呼び出しのkde_kws
引数にshade = True
を渡します。
sns.distplot(subset, hist = False, kde = True,
kde_kws = {'shade': True, 'linewidth': 3},
label = airline)
プロットをシェードするかどうかは、他のプロッティングオプション同様、問題に依存する質問です!プロットをシェーディングするために必要なのは、プロットすることです。 このグラフでは、陰影は重なり合う領域でプロットを区別するのに役立つので、意味があると思います。 さて、ようやく有用な情報が得られました。 アラスカ航空のフライトは、ユナイテッド航空よりも早くなる傾向があります。 次に選択肢があるとき、どちらの航空会社を選ぶべきかわかります!
Rug Plots
平滑化密度だけではなく、分布のすべての値を表示したい場合、rug plotを追加することができます。 これは、X軸上にすべてのデータ点を表示し、実際の値のすべてを視覚化することができます。 seabornのdistplot
を使う利点は、rug = True
の1つのパラメータ呼び出しでrug plotを追加できることです(同様にいくつかのフォーマットもあります)。
多くのデータポイントで rug plot は過密になりますが、あるデータセットではすべてのデータポイントの表示は有用となる可能性があります。 ラグプロットはまた、各データ点でカーネル分布を作るので、密度プロットがどのようにデータがないところに「作る」かを見ることができます。 これらの分布は、元のデータの範囲を超えて漏れ、アラスカ航空の遅延が実際よりも短かったり長かったりするような印象を与えることがあります。 密度プロットのこのアーティファクトに注意し、閲覧者に指摘する必要があります!
結論
この投稿により、1 つまたは複数のカテゴリから単一の変数を視覚化するためのオプションの範囲を提供できたと思います。 経験的累積密度プロットや分位点-分位点プロットなど、作成できる一変量(単一変数)のプロットはさらにありますが、今のところ、ヒストグラムと密度プロット(およびラグプロットも!)のみにしておきます。 選択肢に圧倒されても心配しないでください:練習すれば、良い選択ができるようになりますし、必要であればいつでも助けを求めることができます。 また、多くの場合、最適な選択肢はなく、「正しい」決定は、好みと可視化の目的によって決まります。 良いことに、どんなプロットを作りたいとしても、Pythonでそれを実現する方法があるはずです 可視化は結果を伝えるための効果的な手段であり、利用可能なすべてのオプションを知ることで、データに適した図を選択することができます。
フィードバックや建設的な批判を歓迎します。