seabornプロット関数の概要#
seabornとのやり取りの大部分は、一連のプロット関数を通して行われます。チュートリアルの後の章では、各関数によって提供される特定の機能について説明します。この章では、遭遇するさまざまな種類の関数を、高いレベルで紹介します。
同様のタスクのための同様の関数#
seabornの名前空間はフラットです。すべての機能は最上位レベルでアクセスできます。しかし、コード自体は階層的に構造化されており、異なる手段によって同様の可視化目標を達成する関数のモジュールがあります。「relational」、「distributional」、「categorical」などの名前を見つけるでしょう。ほとんどのドキュメントはこれらのモジュールを中心に構成されています。
たとえば、distributionsモジュールは、データポイントの分布を表すことに特化した関数を定義しています。これには、ヒストグラムのようなよく知られた方法が含まれます。
penguins = sns.load_dataset("penguins")
sns.histplot(data=penguins, x="flipper_length_mm", hue="species", multiple="stack")

カーネル密度推定などの、あまり馴染みのないオプションとともに
sns.kdeplot(data=penguins, x="flipper_length_mm", hue="species", multiple="stack")

モジュール内の関数は、多くの基礎となるコードを共有し、ライブラリの他のコンポーネント(上記の例にあるmultiple="stack"
など)には存在しない可能性のある同様の機能を提供します。これらは、データセットの調査中に異なる視覚表現を切り替えることを容易にするように設計されています。なぜなら、異なる表現はしばしば相補的な強みと弱みを持つからです。
図レベル関数と軸レベル関数#
異なるモジュールの他に、seaborn関数を「軸レベル」または「図レベル」として分類するクロスカット分類があります。上記の例は軸レベル関数です。これらは、関数の戻り値であるmatplotlib.pyplot.Axes
オブジェクトにデータをプロットします。
対照的に、図レベル関数は、通常はFacetGrid
であるseabornオブジェクトを通じてmatplotlibとインターフェースし、図を管理します。各モジュールには、そのさまざまな軸レベル関数に対する統一的なインターフェースを提供する単一の図レベル関数があります。組織は次のようになります。

たとえば、displot()
は、distributionsモジュールの図レベル関数です。そのデフォルトの動作は、背後でhistplot()
と同じコードを使用してヒストグラムを描画することです。
sns.displot(data=penguins, x="flipper_length_mm", hue="species", multiple="stack")

kdeplot()
と同じコードを使用してカーネル密度プロットを描画するには、kind
パラメーターを使用して選択します。
sns.displot(data=penguins, x="flipper_length_mm", hue="species", multiple="stack", kind="kde")

図レベルプロットは、その軸レベルの対応物とほぼ同じように見えますが、いくつかの違いがあります。特に、凡例はプロットの外側に配置されます。それらはわずかに異なる形状も持っています(その詳細は後で説明します)。
図レベル関数によって提供される最も便利な機能は、複数のサブプロットを持つ図を簡単に作成できることです。たとえば、同じ軸上の各ペンギンの種の3つの分布を重ね合わせる代わりに、図の列全体に各分布をプロットすることで「ファセット」できます。
sns.displot(data=penguins, x="flipper_length_mm", hue="species", col="species")

図レベル関数は、その軸レベルの対応物をラップし、種類固有のキーワード引数(ヒストグラムのビンサイズなど)を基礎となる関数に渡します。つまり、柔軟性が低いわけではありませんが、欠点もあります。種類固有のパラメーターは、関数のシグネチャやdocstringsには表示されません。その機能の一部は発見しにくく、特定の目標を達成する方法を理解するには、ドキュメントの2つの異なるページを確認する必要がある場合があります。
軸レベル関数は自己完結型のプロットを作成します#
軸レベル関数は、matplotlib関数のドロップイン置換として機能するように記述されています。軸ラベルと凡例を自動的に追加しますが、描画された軸を超えて何も変更しません。つまり、予測可能な結果で任意に複雑なmatplotlib図に構成できます。
軸レベル関数は内部的にmatplotlib.pyplot.gca()
を呼び出します。これはmatplotlibステートマシンインターフェースにフックして、プロットを「現在アクティブな」軸に描画します。しかし、それらはさらにax=
引数を受け入れ、オブジェクト指向インターフェースと統合して、各プロットが正確にどこに配置されるべきかを指定できます。
f, axs = plt.subplots(1, 2, figsize=(8, 4), gridspec_kw=dict(width_ratios=[4, 3]))
sns.scatterplot(data=penguins, x="flipper_length_mm", y="bill_length_mm", hue="species", ax=axs[0])
sns.histplot(data=penguins, x="species", hue="species", shrink=.8, alpha=.8, legend=False, ax=axs[1])
f.tight_layout()

図レベル関数は独自の図を所有します#
対照的に、図レベル関数は(簡単に)他のプロットと組み合わせることができません。設計上、それらは初期化を含む独自の図を「所有」するため、図レベル関数を使用して既存の軸にプロットを描画するという概念はありません。この制約により、図レベル関数は、凡例をプロットの外側に配置するなどの機能を実装できます。
それにもかかわらず、返されるオブジェクト上のmatplotlib軸にアクセスし、その方法でプロットに他の要素を追加することで、図レベル関数が提供するものを超えることが可能です。
tips = sns.load_dataset("tips")
g = sns.relplot(data=tips, x="total_bill", y="tip")
g.ax.axline(xy1=(10, 2), slope=.2, color="b", dashes=(5, 2))

図レベル関数からのプロットのカスタマイズ#
図レベル関数はFacetGrid
インスタンスを返し、これはサブプロットの編成について「スマート」な方法でプロットの属性をカスタマイズするためのいくつかのメソッドを持っています。たとえば、1行のコードを使用して外部軸のラベルを変更できます。
g = sns.relplot(data=penguins, x="flipper_length_mm", y="bill_length_mm", col="sex")
g.set_axis_labels("Flipper length (mm)", "Bill length (mm)")

便利ですが、これは少し複雑さを追加します。なぜなら、このメソッドはmatplotlib APIの一部ではなく、図レベル関数を使用する場合にのみ存在する必要があるからです。
図のサイズの指定#
matplotlibプロットのサイズを増減するには、プロットの設定中(たとえば、グローバルrcParamsで、またはmatplotlib.pyplot.subplots()
のfigsize
パラメーターを使用して)、または図オブジェクトのメソッドを呼び出すことによって(たとえば、matplotlib.Figure.set_size_inches()
)、全体の図の幅と高さを設定します。seabornで軸レベル関数を使用する場合、同じルールが適用されます。プロットのサイズは、それが属する図のサイズとその図における軸のレイアウトによって決まります。
図レベル関数を使用する場合、いくつかの重要な違いがあります。まず、関数自体に図のサイズを制御するパラメーターがあります(ただし、これらは実際には図を管理する基礎となるFacetGrid
のパラメーターです)。第二に、これらのパラメーターheight
とaspect
は、matplotlibのパラメーターwidth
、height
とは少し異なる方法でサイズをパラメーター化します(seabornパラメーターを使用すると、width = height * aspect
)。最も重要なのは、パラメーターが全体の図のサイズではなく、各サブプロットのサイズに対応することです。
これらのアプローチの違いを示すために、1つのサブプロットを持つmatplotlib.pyplot.subplots()
のデフォルトの出力は次のとおりです。
f, ax = plt.subplots()

複数の列を持つ図は同じ全体のサイズになりますが、軸は水平方向に圧縮されて空間に収まります。
f, ax = plt.subplots(1, 2, sharey=True)

対照的に、図レベル関数によって作成されたプロットは正方形になります。それを示すために、FacetGrid
を直接使用して空のプロットを設定しましょう。これはrelplot()
、displot()
、またはcatplot()
などの関数で舞台裏で行われます。
g = sns.FacetGrid(penguins)

列を追加すると、図自体が広くなり、サブプロットのサイズと形状は同じになります。
g = sns.FacetGrid(penguins, col="sex")

そして、図の行と列の総数を考慮せずに、各サブプロットのサイズと形状を調整できます。
g = sns.FacetGrid(penguins, col="sex", height=3.5, aspect=.75)

つまり、図全体のサイズ調整方法を考えずにファセット変数を割り当てることができます。欠点としては、図のサイズを変更したい場合、matplotlibとは少し異なる動作をすることを覚えておく必要があるということです。
図レベル関数の相対的なメリット#
上記で説明した長所と短所の概要を以下に示します。
利点 |
欠点 |
---|---|
データ変数による簡単なファセッティング |
関数シグネチャにないパラメータが多い |
凡例がデフォルトでプロットの外にある |
より大きなmatplotlib図の一部にすることができない |
図レベルのカスタマイズが容易 |
matplotlibとは異なるAPI |
図のサイズパラメーター化が異なる |
図のサイズパラメーター化が異なる |
全体として、図レベル関数は初心者にとって混乱を招く可能性のある複雑さを追加しますが、その独自の機能により、追加の機能を提供します。チュートリアルドキュメントでは主に図レベル関数が使用されています。これは、よりクリーンなプロットを作成するためであり、ほとんどのアプリケーションではその使用をお勧めします。図レベル関数が適切でないのは、複数の異なるプロットの種類を構成する複雑なスタンドアロン図を作成する必要がある場合です。この場合、matplotlibを使用して直接図を設定し、軸レベル関数を使用して個々のコンポーネントを埋め込むことをお勧めします。
データに対する複数のビューの組み合わせ#
seabornの2つの重要なプロット関数は、上記で説明した分類スキームにはうまく適合しません。これらの関数、jointplot()
とpairplot()
は、異なるモジュールの複数のプロットの種類を使用して、単一の図でデータセットの複数の側面を表します。両方のプロットは図レベル関数であり、デフォルトで複数のサブプロットを持つ図を作成します。しかし、図の管理には異なるオブジェクトを使用します。それぞれJointGrid
とPairGrid
です。
jointplot()
は、2つの変数の関係または同時分布をプロットし、それぞれの一変量分布を示す周辺軸を追加します。
sns.jointplot(data=penguins, x="flipper_length_mm", y="bill_length_mm", hue="species")

pairplot()
も同様で、同時ビューと周辺ビューを組み合わせますが、単一の関係に焦点を当てるのではなく、変数のすべてのペアワイズの組み合わせを同時に視覚化します。
sns.pairplot(data=penguins, hue="species")

これらの関数は、すでに説明した軸レベル関数(scatterplot()
とkdeplot()
)を使用しており、異なる表現に簡単に切り替えることができるkind
パラメーターも備えています。
sns.jointplot(data=penguins, x="flipper_length_mm", y="bill_length_mm", hue="species", kind="hist")
