06.7.31
UpSetプロットで集合の交差を正確に比較
upsetplot ライブラリに、各スキルの True / False を列にした DataFrame を set_index で MultiIndex にして value_counts() した Series を渡すだけで描画できます。読み終えると、200 人の中で最も多いスキルの組み合わせを棒の高さから見つけ、min_subset_size で少数パターンを隠し sort_by で並び順を切り替えて自分の集合データを整理できるようになります。直感 #
社員 200 人が Python・SQL・機械学習・統計・可視化の 5 つのスキルをそれぞれ持つか持たないかを調べたとします。「Python と SQL は両方できるが機械学習はできない人は何人か」という問いに、5 つの円を重ねたベン図は答えられません。5 集合のベン図は 31 個の領域が入り組み、面積と人数も一致しないからです。UpSet プロットは発想を変えて、5 つのスキルを行に並べ、組み合わせを列にします。列の中で黒丸が付いた行がその組み合わせに含まれるスキルで、列の上の棒がその組み合わせの人数です。棒を高い順に並べれば「最も多いスキルセット」が左端に来ます。
Python で描く #
次のコードは、各スキルを異なる確率(Python 65%、SQL 55% など)で独立に持つ 200 人を作り、upsetplot 用の MultiIndex 形式に変換して、3 人以上いる組み合わせだけを件数順に描きます。
| |

実行結果の読み方 #
上部の棒の高さが各組み合わせの人数で、左端が最も多いスキルセットです。各棒の下の行列で黒丸が付いた行が、その組み合わせに含まれるスキルで、黒丸が 1 つだけの列は「そのスキルしか持たない人」の数になります。左側の横棒は各スキル単独の保有者数(セットサイズ)で、Python が 65% の約 130 人で最大、機械学習が 35% の約 70 人で最小になるはずです。独立に生成したデータなので、たとえば「Python と SQL のみ」の期待人数は \(200 \times 0.65 \times 0.55 \times 0.65 \times 0.60 \times 0.50 \approx 14\) 人で、棒の高さがこの近辺に来ていれば読み方が正しいと確認できます。
使いどころと落とし穴 #
UpSet プロットは、3〜7 集合の交差パターンを件数で正確に比べたいときの図で、ベン図が 4 集合以上で面積の正確さを失うのに対し、棒の高さで件数をそのまま読めます。集合が 2 つなら普通のベン図で十分で、15 集合を超えるとパターン数が数万に膨れて意味のある読解ができないので、集合を絞ってください。5 集合で最大 32 パターンが出るため、min_subset_size で少数パターンを隠さないと図が横に伸びすぎて棒が細くなります。既定の件数順(sort_by="cardinality")が常に最適とは限らず、「1 スキルのみ → 2 スキル → 3 スキル」と構成の複雑さで眺めたいなら sort_by="degree" に切り替えます。集合の包含関係(A は B の部分集合か)だけが関心ならオイラー図、集合間の移動(昨年 A だった人が今年 B へ)が関心ならサンキーダイアグラムが適しています。