06.2.4
バイオリンプロット
sns.violinplot(data=penguins, x="species", y="bill_length_mm") の 1 行でペンギン 3 種のくちばしの長さが 3 本のバイオリンになり、「Adelie は 39 mm に 1 つの山、Chinstrap は 49 mm で幅が広い」と形の違いが読めます。読み終えると、inner で内側の表示を切り替え、cut=0 で裾のはみ出しを止め、サンプル数が少ないカテゴリの胴を過信しない読み方ができるようになります。直感 #
ペンギン 3 種のくちばしの長さを箱ひげ図にすると、Adelie の中央値 39 mm と Gentoo の 47 mm の差は見えますが、箱の中で値がどう分布しているかは見えません。バイオリンプロットは、各種の値から密度曲線を推定し、それを縦向きにして左右に鏡写しにした「胴」を描きます。胴が太い高さに値が集まり、細い高さは値がまれで、2 か所で膨らめば山が 2 つあると分かります。胴の中央には細い箱ひげが埋め込まれていて、白い点が中央値、太い線が四分位範囲(IQR)です。密度曲線を使うので、密度プロット と同じくバンド幅の選び方が形を左右し、サンプルが少ないカテゴリでも滑らかな胴が描かれてしまう点は覚えておきます。
何が起きているか(ステップで見る) #
コードを読む前に、この手法が図の上で何をしているかを追ってみましょう。「再生」を押すか、スライダーを動かすと 1 手順ずつ進みます。
見るポイント:密度曲線は「各点に置いた小さな山の合計」。階級の切れ目に左右されない代わりに、山の幅(バンド幅)が形を決める。
Python で描く #
次のコードは seaborn 付属の penguins データから欠損行を除き、くちばしの長さを種別に 3 本のバイオリンで並べます。
| |

実行結果の読み方 #
Adelie の胴は 39 mm 付近で最も太く、上下に対称な 1 つの山です。Chinstrap は 49 mm 付近に山があり、胴が上下に長く伸びて幅も広いため、ばらつきが 3 種の中で最も大きいと読めます。Gentoo は 47 mm 付近に山があり、Chinstrap より胴が引き締まっています。白い点(中央値)を横に比べれば「Adelie だけが明らかに短い」ことが分かり、箱ひげ図と同じ結論を保ちながら、胴の形で「2 つの山はない」ことまで確認できます。
使いどころと落とし穴 #
バイオリンプロットが向くのは、3〜8 カテゴリで分布の形(山の数、裾の重さ)を比べたいときで、箱ひげ図が隠す多峰性を見逃したくない場面です。落とし穴は 2 つあります。第一に、密度推定は 0 以上しか取らないデータでも負の領域に裾を伸ばすので、長さや価格の列では cut=0 で止めないと「存在しない値」の胴が描かれます。第二に、羽数が 20 のカテゴリと 150 のカテゴリを同じ幅で描くと、少ないほうの胴が実態以上に滑らかで信頼できそうに見えます。scale="count" で太さに羽数を反映させるか、n を注記します。カテゴリが 10 を超えて胴が窮屈になるなら リッジラインプロット で横向きに並べ、個票まで見せたいなら Swarmplot を重ねます。
- 箱ひげ図 — 中央値・四分位数・外れ値を比較
- Swarmplot — 個々のデータを重ならず配置
- リッジラインプロット — カテゴリ別の分布を重ねて比較