度数表に使うcrosstab
pd.crosstabで2つのカテゴリ列の度数または割合によるクロス集計表を計算します。
「度数表に使うcrosstab」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。
クロス集計とは
クロス集計(crosstab)は、データセット内で2つ以上のカテゴリ変数の値の組み合わせが何回現れるかを数えるものです。これは、集計に特化して設計されたピボットテーブルの一種です。Pandasのpd.crosstab()を使うと、groupby()やpivot_table()を明示的に呼び出さずに、これらの度数表を簡潔に計算できます。
基本的なcrosstab()の呼び出し
最小限のpd.crosstab(index, columns)の呼び出しでは、2つの配列のような入力(通常はDataFrameの列)を受け取り、度数表を返します。行は1つ目の引数の一意な値に対応し、列は2つ目の引数の一意な値に対応します。各セルには、元のデータで両方の値が同時に現れる行数が入ります。
import pandas as pd
df = pd.DataFrame({
'gender': ['M', 'F', 'M', 'F', 'M', 'F', 'M'],
'product': ['A', 'A', 'B', 'B', 'A', 'B', 'B']
})
ct = pd.crosstab(df['gender'], df['product'])
print(ct)
# product A B
# gender
# F 1 2
# M 2 2行名と列名のカスタマイズ
rownamesとcolnamesパラメータを使うと、出力の行軸と列軸に意味のある名前を付け、デフォルトのSeries名を上書きできます。DataFrameの元の列名だけでは、作成する表の文脈で意味が分かりにくい場合に便利です。
ct = pd.crosstab(
df['gender'], df['product'],
rownames=['Customer Gender'],
colnames=['Purchased Product']
)
print(ct)
# Purchased Product A B
# Customer Gender
# F 1 2
# M 2 2マージン(行と列の合計)の追加
margins=Trueを渡すと、すべての値を合計する行と列を追加できます。マージンのラベルはデフォルトで'All'ですが、margins_nameで変更できます。マージン行には列ごとの合計件数、マージン列には行ごとの合計件数が表示され、右下のセルには総合計が表示されます。
ct = pd.crosstab(df['gender'], df['product'],
margins=True, margins_name='Total')
print(ct)
# product A B Total
# gender
# F 1 2 3
# M 2 2 4
# Total 3 4 7割合への正規化
normalizeパラメータを渡すと、件数を割合に変換できます。normalize=Trueまたはnormalize='all'を指定すると、総合計で割ります。normalize='index'では行の割合を計算し、各行の合計が1.0になります。normalize='columns'では列の割合を計算し、各列の合計が1.0になります。グループのサイズが異なる場合、割合のほうが単純な件数よりも多くの情報を示します。
# Row proportions: what fraction of each gender bought each product?
print(pd.crosstab(df['gender'], df['product'], normalize='index').round(2))
# product A B
# gender
# F 0.33 0.67
# M 0.50 0.50
# All proportions: each cell as fraction of grand total
print(pd.crosstab(df['gender'], df['product'], normalize=True).round(2))件数ではなく値を集計する
デフォルトでは、crosstabは行数を数えます。代わりに、valuesとaggfuncパラメータを渡して数値列を集計することもできます。これはpivot_table()と似ています。たとえば、性別と商品の組み合わせごとの総売上を計算できます。これにより、crosstabはpivot_tableとほぼ同等になりますが、度数表の用途では構文が少し簡潔です。
df['revenue'] = [100, 80, 150, 120, 200, 90, 130]
# Sum revenue by gender and product instead of counting
ct_rev = pd.crosstab(
df['gender'], df['product'],
values=df['revenue'],
aggfunc='sum'
)
print(ct_rev)
# product A B
# gender
# F 80 210
# M 300 280複数レベルのクロス集計
indexまたはcolumnsにリストを渡すと、行または列に複数のレベルを持つクロス集計を作成できます。結果はMultiIndexになり、より細かな内訳を確認できます。たとえば、行を性別と地域、列を商品としてクロス集計すると、性別・地域・商品のすべての組み合わせを確認できます。
df['region'] = ['East', 'West', 'East', 'West', 'East', 'East', 'West']
ct_multi = pd.crosstab(
[df['gender'], df['region']],
df['product'],
margins=True
)
print(ct_multi)
# product A B All
# gender region
# F East 0 1 1
# West 1 1 2
# M East 2 1 3
# West 0 1 1
# All 3 4 7crosstab()とpivot_table()の比較
pd.crosstab()とpd.pivot_table()には大きな重複があります。crosstabは度数のカウントに最適化されており、配列のような入力を直接受け取る(DataFrameでなくてもよい)ため、簡単な集計では少し簡潔に書けます。pivot_tableはDataFrameを操作し、任意の集計関数を標準でサポートします。単純なカウント処理にはcrosstabが慣用的な選択で、数値の集計にはpivot_tableを使うのがおすすめです。
# crosstab (more concise for counting)
print(pd.crosstab(df['gender'], df['product']))
# Equivalent pivot_table
print(pd.pivot_table(df, index='gender', columns='product',
aggfunc='size', fill_value=0))
# Both produce the same resultカイ二乗検定の準備
クロス集計表は、2つのカテゴリ変数に統計的な関連があるかを検定する独立性のカイ二乗検定の標準的な入力です。scipy.stats.chi2_contingency()関数には、クロス集計表の配列を直接渡せます。これは統計的なデータ分析におけるcrosstabの最も一般的な用途の1つで、表を作成してから同じ流れで検定できます。
from scipy import stats
ct = pd.crosstab(df['gender'], df['product'])
# Convert to numpy array for scipy
chi2, p, dof, expected = stats.chi2_contingency(ct.values)
print(f'Chi2: {chi2:.2f}')
print(f'P-value: {p:.4f}')
print(f'Degrees of freedom: {dof}')
# p > 0.05 means no significant associationクロス集計表をヒートマップで可視化する
カテゴリが多いクロス集計表は、数値のままでは解釈しにくくなります。sns.heatmap()を使ってヒートマップとして可視化すると、パターンがすぐに見えるようになります。頻度の高いセルは明るい色で表示されます。正規化した結果を渡せば単純な件数ではなく割合を表示でき、annot=Trueを使えば各セルの値も表示できます。
import seaborn as sns
import matplotlib.pyplot as plt
ct_norm = pd.crosstab(df['gender'], df['product'], normalize='index')
# sns.heatmap(ct_norm, annot=True, fmt='.0%', cmap='Blues')
# plt.title('Purchase Rate by Gender and Product')
# plt.tight_layout()
# plt.show()
print('Normalised crosstab ready for heatmap:')
print(ct_norm.round(2))実践例:アンケート分析
クロス集計の一連のワークフローを完成させます。調査データを読み込み、人口統計変数と回答変数の組み合わせごとの度数表を計算し、行単位で正規化して回答率を求め、強い傾向がないかを特定します。これは市場調査、A/Bテスト、ユーザーセグメンテーションで標準的に使われる分析パイプラインで、Pandasのコード10行未満で完了できます。
# Simulate a survey dataset
survey = pd.DataFrame({
'age_group': ['18-25', '26-35', '18-25', '36-45', '26-35', '36-45'],
'satisfaction': ['High', 'Low', 'High', 'Medium', 'High', 'Low']
})
ct = pd.crosstab(survey['age_group'], survey['satisfaction'],
margins=True, margins_name='Total')
print(ct)
rates = pd.crosstab(survey['age_group'], survey['satisfaction'],
normalize='index').round(2)
print(rates)理解度チェック
このレッスンで学んだ、度数表を作成するためのpd.crosstabの理解度を確認しましょう。
レッスンのまとめ
このレッスンでは、pd.crosstab()によって2つのカテゴリ変数の組み合わせごとの度数を計算できること、normalizeによって度数を行・列・全体の割合に変換できること、margins=Trueによって行と列の合計を追加できることを学びました。また、クロス集計の出力はカイ二乗検定やヒートマップによる可視化にそのまま利用できます。次は、DatetimeIndexと期間範囲を使って時系列データを扱います。
よくある質問
「度数表に使うcrosstab」レッスンは無料ですか?
はい。「度数表に使うcrosstab」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。
「度数表に使うcrosstab」で何を学びますか?
pd.crosstabで2つのカテゴリ列の度数または割合によるクロス集計表を計算します。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Pandas & NumPy Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「度数表に使うcrosstab」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPandas & NumPy Academyレッスンでコードを書いて実行できますか?
はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。