構造化された複数プロットグリッドの構築#

多次元データを探索する場合、データセットの異なるサブセットに同じプロットの複数のインスタンスを描画するのが有効なアプローチです。この手法は、「格子」プロットまたは「トレリス」プロットと呼ばれることもあり、“スモールマルチプル”の概念に関連しています。これにより、閲覧者は複雑なデータセットに関する大量の情報をすばやく抽出できます。Matplotlibは、複数の軸を持つ図を作成するための優れたサポートを提供しています。seabornはこれを基盤として、プロットの構造をデータセットの構造に直接リンクします。

図レベルの関数は、このチュートリアルの章で説明されているオブジェクトの上に構築されています。ほとんどの場合、これらの関数を使用することをお勧めします。これらは、各グリッド内の複数のプロットを同期させる重要なブックキーピングを処理します。この章では、基礎となるオブジェクトのしくみについて説明します。これは、高度なアプリケーションで役立つ場合があります。

条件付きスモールマルチプル#

FacetGrid クラスは、変数の分布や複数の変数間の関係を、データセットのサブセット内で個別に視覚化する場合に役立ちます。FacetGrid は、最大3つの次元(rowcolhue)で描画できます。最初の2つは、結果の軸の配列と明確に対応しています。hue変数は、奥行き軸に沿った3次元と見なしてください。異なるレベルは異なる色でプロットされます。

relplot()displot()catplot()lmplot() は、すべて内部でこのオブジェクトを使用し、完了するとオブジェクトを返します。そのため、さらに微調整するために使用できます。

このクラスは、データフレームと、グリッドの行、列、または色相の次元を形成する変数の名前を使用して、FacetGrid オブジェクトを初期化することによって使用されます。これらの変数はカテゴリ型または離散型である必要があります。その後、変数の各レベルのデータが、その軸に沿ったファセットに使用されます。たとえば、tips データセットで、ランチとディナーの違いを調べたいとします。

tips = sns.load_dataset("tips")
g = sns.FacetGrid(tips, col="time")
../_images/axis_grids_4_0.png

このようにグリッドを初期化すると、matplotlibの図と軸が設定されますが、何も描画されません。

このグリッドにデータを視覚化する主なアプローチは、FacetGrid.map() メソッドを使用することです。プロット関数と、プロットするデータフレーム内の変数の名前を指定します。ヒストグラムを使用して、これらの各サブセットでのチップの分布を見てみましょう。

g = sns.FacetGrid(tips, col="time")
g.map(sns.histplot, "tip")
../_images/axis_grids_6_0.png

この関数は、図を描画し、軸に注釈を付けます。うまくいけば、1つのステップで完成したプロットが生成されます。関係プロットを作成するには、複数の変数名を渡すだけです。キーワード引数を指定することもできます。これはプロット関数に渡されます。

g = sns.FacetGrid(tips, col="sex", hue="smoker")
g.map(sns.scatterplot, "total_bill", "tip", alpha=.7)
g.add_legend()
../_images/axis_grids_8_0.png

クラスコンストラクターに渡すことができる、グリッドの外観を制御するためのオプションがいくつかあります。

g = sns.FacetGrid(tips, row="smoker", col="time", margin_titles=True)
g.map(sns.regplot, "size", "total_bill", color=".3", fit_reg=False, x_jitter=.1)
../_images/axis_grids_10_0.png

margin_titles は、matplotlib APIで正式にサポートされておらず、すべての場合でうまく機能するとは限らないことに注意してください。特に、現在、プロットの外側にある凡例とは一緒に使用できません。

図のサイズは、*各*ファセットの高さとアスペクト比を指定することによって設定されます。

g = sns.FacetGrid(tips, col="day", height=4, aspect=.5)
g.map(sns.barplot, "sex", "total_bill", order=["Male", "Female"])
../_images/axis_grids_12_0.png

ファセットのデフォルトの順序は、DataFrameの情報から派生します。ファセットの定義に使用される変数がカテゴリ型の場合、カテゴリの順序が使用されます。それ以外の場合、ファセットはカテゴリレベルの出現順になります.ただし、適切な *_order パラメーターを使用して、ファセット次元の順序を指定することは可能です.

ordered_days = tips.day.value_counts().index
g = sns.FacetGrid(tips, row="day", row_order=ordered_days,
                  height=1.7, aspect=4,)
g.map(sns.kdeplot, "total_bill")
../_images/axis_grids_14_0.png

任意のseabornカラーパレット(つまり、color_palette() に渡すことができるもの)を指定できます。hue 変数の値の名前を有効なmatplotlibの色にマップする辞書を使用することもできます。

pal = dict(Lunch="seagreen", Dinner=".7")
g = sns.FacetGrid(tips, hue="time", palette=pal, height=5)
g.map(sns.scatterplot, "total_bill", "tip", s=100, alpha=.5)
g.add_legend()
../_images/axis_grids_16_0.png

1つの変数のレベルが多い場合は、列に沿ってプロットできますが、複数の行にまたがるように「ラップ」できます。これを行う場合、row 変数は使用できません。

attend = sns.load_dataset("attention").query("subject <= 12")
g = sns.FacetGrid(attend, col="subject", col_wrap=4, height=2, ylim=(0, 10))
g.map(sns.pointplot, "solutions", "score", order=[1, 2, 3], color=".3", errorbar=None)
../_images/axis_grids_18_0.png

FacetGrid.map() を使用してプロットを描画したら(複数回呼び出すことができます)、プロットのいくつかの側面を調整することができます。FacetGrid オブジェクトには、より高いレベルの抽象化で図を操作するためのメソッドも多数あります。最も一般的なのは FacetGrid.set() で、内部ファセットに軸ラベルがないという事実を尊重する FacetGrid.set_axis_labels() など、より特化したメソッドもあります。例えば

with sns.axes_style("white"):
    g = sns.FacetGrid(tips, row="sex", col="smoker", margin_titles=True, height=2.5)
g.map(sns.scatterplot, "total_bill", "tip", color="#334488")
g.set_axis_labels("Total bill (US Dollars)", "Tip")
g.set(xticks=[10, 30, 50], yticks=[2, 6, 10])
g.figure.subplots_adjust(wspace=.02, hspace=.02)
../_images/axis_grids_20_0.png

さらにカスタマイズするには、基礎となるmatplotlibの Figure および Axes オブジェクトを直接操作できます。これらは、それぞれ figure および axes_dict にメンバー属性として格納されます。行または列のファセット化なしで図を作成する場合、ax 属性を使用して単一の軸に直接アクセスすることもできます。

g = sns.FacetGrid(tips, col="smoker", margin_titles=True, height=4)
g.map(plt.scatter, "total_bill", "tip", color="#338844", edgecolor="white", s=50, lw=1)
for ax in g.axes_dict.values():
    ax.axline((0, 0), slope=.2, c=".2", ls="--", zorder=0)
g.set(xlim=(0, 60), ylim=(0, 14))
../_images/axis_grids_22_0.png

カスタム関数の使用#

FacetGrid を使用する際に、既存のmatplotlibおよびseaborn関数に限定されません。ただし、正しく動作するには、使用する関数がいくつかのルールに従う必要があります。

  1. 「現在アクティブな」matplotlib Axes にプロットする必要があります。これは、matplotlib.pyplot 名前空間の関数に当てはまります。 matplotlib.pyplot.gca() を呼び出して、現在の Axes への参照を取得し、そのメソッドを直接操作できます。

  2. 位置引数でプロットするデータを受け入れる必要があります。内部的には、FacetGrid は、FacetGrid.map() に渡された名前付きの位置引数ごとに、データの Series を渡します。

  3. color および label キーワード引数を受け入れることができ、理想的には、それらを使用して何か役に立つことを行う必要があります。ほとんどの場合、**kwargs の汎用辞書をキャッチして、基礎となるプロット関数に渡すのが最も簡単です。

プロットできる関数の最小限の例を見てみましょう。この関数は、各ファセットのデータの単一ベクトルのみを受け取ります。

from scipy import stats
def quantile_plot(x, **kwargs):
    quantiles, xr = stats.probplot(x, fit=False)
    plt.scatter(xr, quantiles, **kwargs)

g = sns.FacetGrid(tips, col="sex", height=4)
g.map(quantile_plot, "total_bill")
../_images/axis_grids_24_0.png

2変量プロットを作成する場合、x軸変数を最初に、y軸変数を2番目に受け入れるように関数を記述する必要があります。

def qqplot(x, y, **kwargs):
    _, xr = stats.probplot(x, fit=False)
    _, yr = stats.probplot(y, fit=False)
    plt.scatter(xr, yr, **kwargs)

g = sns.FacetGrid(tips, col="smoker", height=4)
g.map(qqplot, "total_bill", "tip")
../_images/axis_grids_26_0.png

matplotlib.pyplot.scatter()color および label キーワード引数を受け入れ、それらを使用して正しい処理を行うため、問題なく色相ファセットを追加できます。

g = sns.FacetGrid(tips, hue="time", col="sex", height=4)
g.map(qqplot, "total_bill", "tip")
g.add_legend()
../_images/axis_grids_28_0.png

ただし、color および label キーワード引数で期待どおりに動作しない関数をマップしたい場合があります。この場合、それらを明示的にキャッチし、カスタム関数のロジックで処理する必要があります。たとえば、このアプローチでは、FacetGrid APIとうまく連携しない matplotlib.pyplot.hexbin() をマップできます。

def hexbin(x, y, color, **kwargs):
    cmap = sns.light_palette(color, as_cmap=True)
    plt.hexbin(x, y, gridsize=15, cmap=cmap, **kwargs)

with sns.axes_style("dark"):
    g = sns.FacetGrid(tips, hue="time", col="time", height=4)
g.map(hexbin, "total_bill", "tip", extent=[0, 50, 0, 10]);
../_images/axis_grids_30_0.png

ペアワイズデータ関係のプロット#

PairGrid (seaborn.PairGrid) を使用すると、同じプロットタイプを使用して小さなサブプロットのグリッドをすばやく描画し、それぞれにデータを視覚化できます。PairGrid では、各行と列が異なる変数に割り当てられるため、結果のプロットはデータセット内の各ペアワイズ関係を示します。このスタイルのプロットは、各関係を示す最も一般的な方法であるため、「散布図行列」と呼ばれることもありますが、PairGrid は散布図に限定されません。

FacetGridPairGrid の違いを理解することが重要です。前者では、各ファセットは他の変数の異なるレベルで条件付けられた同じ関係を示します。後者では、各プロットは異なる関係を示します(ただし、上三角と下三角はミラーリングされたプロットになります)。PairGrid を使用すると、データセット内の興味深い関係を非常に迅速かつ非常に高レベルで要約できます。

このクラスの基本的な使い方は FacetGrid と非常によく似ています。最初にグリッドを初期化し、次にプロット関数を map メソッドに渡すと、各サブプロットで呼び出されます。また、より高速なプロットのために柔軟性をトレードオフするコンパニオン関数 pairplot() もあります。

iris = sns.load_dataset("iris")
g = sns.PairGrid(iris)
g.map(sns.scatterplot)
../_images/axis_grids_32_0.png

対角線上に異なる関数をプロットして、各列の変数の単変量分布を表示することができます。ただし、軸の目盛りはこのプロットの個数または密度軸に対応しないことに注意してください。

g = sns.PairGrid(iris)
g.map_diag(sns.histplot)
g.map_offdiag(sns.scatterplot)
../_images/axis_grids_34_0.png

このプロットを使用する非常に一般的な方法は、別のカテゴリ変数によって観測値を色分けすることです。たとえば、irisデータセットには、3種類のアイリスの花それぞれについて4つの測定値があるため、それらがどのように異なるかを確認できます。

g = sns.PairGrid(iris, hue="species")
g.map_diag(sns.histplot)
g.map_offdiag(sns.scatterplot)
g.add_legend()
../_images/axis_grids_36_0.png

デフォルトでは、データセット内のすべての数値列が使用されますが、必要に応じて特定の関係に焦点を当てることができます。

g = sns.PairGrid(iris, vars=["sepal_length", "sepal_width"], hue="species")
g.map(sns.scatterplot)
../_images/axis_grids_38_0.png

上三角と下三角で異なる関数を使用して、関係の異なる側面を強調することもできます。

g = sns.PairGrid(iris)
g.map_upper(sns.scatterplot)
g.map_lower(sns.kdeplot)
g.map_diag(sns.kdeplot, lw=3, legend=False)
../_images/axis_grids_40_0.png

対角線上に恒等関係を持つ正方形グリッドは実際には特別な場合であり、行と列に異なる変数を使用してプロットできます。

g = sns.PairGrid(tips, y_vars=["tip"], x_vars=["total_bill", "size"], height=4)
g.map(sns.regplot, color=".3")
g.set(ylim=(-1, 11), yticks=[0, 5, 10])
../_images/axis_grids_42_0.png

もちろん、美的属性は設定可能です。たとえば、異なるパレットを使用したり(たとえば、hue 変数の順序を表示するため)、キーワード引数をプロット関数に渡したりできます。

g = sns.PairGrid(tips, hue="size", palette="GnBu_d")
g.map(plt.scatter, s=50, edgecolor="white")
g.add_legend()
../_images/axis_grids_44_0.png

PairGrid は柔軟性がありますが、データセットをすばやく確認するには、pairplot() を使用する方が簡単な場合があります。この関数は、デフォルトで散布図とヒストグラムを使用しますが、他にもいくつかの種類が追加されます(現在、非対角線に回帰プロット、対角線にKDEをプロットすることもできます)。

sns.pairplot(iris, hue="species", height=2.5)
../_images/axis_grids_46_0.png

キーワード引数を使用してプロットの美観を制御することもでき、さらに調整するために PairGrid インスタンスを返します。

g = sns.pairplot(iris, hue="species", palette="Set2", diag_kind="kde", height=2.5)
../_images/axis_grids_48_0.png