2 つのカテゴリ変数の組み合わせごとに集計したいとき、pivot_table を使う方法が一般的ですが、pandas の crosstab を使えばもっと手軽にクロス集計表を作れます。
基本的な使い方
crosstab は 2 つのシリーズ(列)を渡すだけで、出現回数のクロス集計表を生成します。
import pandas as pd df = pd.DataFrame({ "department": ["Sales", "Sales", "Engineering", "Engineering", "Sales", "Engineering"], "gender": ["M", "F", "M", "F", "M", "F"], "salary": [500, 600, 700, 650, 550, 680] }) ct = pd.crosstab(df["department"], df["gender"]) print(ct)
行に department、列に gender がとられ、各セルにはその組み合わせの件数が入ります。アンケートの集計や属性の分布を確認するのに便利です。
margins で合計を追加する
margins=True を指定すると、行と列の合計が追加されます。
ct = pd.crosstab(df["department"], df["gender"], margins=True) print(ct)
合計行・合計列のラベルはデフォルトで "All" になります。margins_name 引数で変更することも可能です。
値を集計する
件数ではなく特定の値を集計したい場合は、values と aggfunc を組み合わせます。
ct = pd.crosstab( df["department"], df["gender"], values=df["salary"], aggfunc="mean" ) print(ct)
この例では部門×性別ごとの平均給与が計算されます。aggfunc には "sum"、"mean"、"median" など任意の集計関数を指定できます。
2 変数のクロス集計に特化。DataFrame を渡す必要がなく、シリーズを直接指定できる
より汎用的なピボット操作。DataFrame のメソッドとして呼び出す
normalize で比率を表示する
normalize 引数を使うと、件数の代わりに比率を表示できます。
ct = pd.crosstab(df["department"], df["gender"], normalize="index") print(ct)
| normalize="index" | 行ごとの比率(各行の合計が 1) |
| normalize="columns" | 列ごとの比率(各列の合計が 1) |
| normalize="all" | 全体に対する比率(全セルの合計が 1) |
「部門ごとの男女比」を見たいなら normalize="index"、「性別ごとの部門分布」を見たいなら normalize="columns" を指定します。
3 つ以上の変数でクロス集計する
行や列にリストを渡すことで、3 つ以上の変数を組み合わせた集計も可能です。
df["level"] = ["Junior", "Senior", "Senior", "Junior", "Junior", "Senior"] ct = pd.crosstab([df["department"], df["level"]], df["gender"]) print(ct)
行が MultiIndex になり、部門×レベル×性別の 3 次元集計が得られます。ただし変数が増えるほど表が複雑になるため、可読性とのバランスには注意が必要です。
crosstab はクロス集計に特化しているぶん、pivot_table よりもシンプルに書けます。2 変数の関係を素早く確認したいときにはまず crosstab を試してみるのがおすすめです。