Compute frequency counts and cross-tabulation summaries using the Pandas pd.crosstab() function. Calculate factor relationships, compute percentages using normalization, apply aggregation functions, and add row/column margins.
pd.crosstab() function builds a frequency table of two or more categorical factors. By default, it counts frequency, but it can also compute summary statistics when combined with numerical values and aggregation functions.import pandas as pd
df = pd.DataFrame({
"SECTION": ["A", "A", "A", "B", "B", "B", "B"],
"RESULT": ["Pass", "Pass", "Fail", "Pass", "Fail", "Fail", "Pass"],
"SCORE": [85, 90, 40, 78, 45, 35, 88]
})
print(df)
assert df.shape == (7, 3)
Expected output
SECTION RESULT SCORE
0 A Pass 85
1 A Pass 90
2 A Fail 40
3 B Pass 78
4 B Fail 45
5 B Fail 35
6 B Pass 88
pd.crosstab() to compute frequency counts across factor levels.ct = pd.crosstab(df["SECTION"], df["RESULT"])
print(ct)
assert ct.loc["A", "Pass"] == 2
Expected output
RESULT Fail Pass
SECTION
A 1 2
B 2 2
margins=True to display row and column totals. Customize the label using margins_name.ct_margins = pd.crosstab(df["SECTION"], df["RESULT"], margins=True, margins_name="Total")
print(ct_margins)
assert ct_margins.loc["Total", "Total"] == 7
Expected output
RESULT Fail Pass Total
SECTION
A 1 2 3
B 2 2 4
Total 3 4 7
normalize=True to get total proportions, or normalize="index" / normalize="columns" to calculate row-wise or column-wise relative percentages.ct_norm = pd.crosstab(df["SECTION"], df["RESULT"], normalize="index") * 100
print(ct_norm.round(1))
assert round(ct_norm.loc["B", "Pass"], 1) == 50.0
Expected output
RESULT Fail Pass
SECTION
A 33.3 66.7
B 50.0 50.0
values along with an aggfunc (e.g., "mean", "sum", "max") to summarize numerical metrics across categories.ct_mean = pd.crosstab(df["SECTION"], df["RESULT"], values=df["SCORE"], aggfunc="mean")
print(ct_mean)
assert ct_mean.loc["A", "Pass"] == 87.5
Expected output
RESULT Fail Pass
SECTION
A 40.0 87.5
B 40.0 83.0
GENDER (["M", "F", "M", "F", "F"]) and GRADE (["A", "B", "A", "A", "B"]) with row and column totals enabled (margins=True). Verify that the overall total equals 5.gender = pd.Series(["M", "F", "M", "F", "F"], name="GENDER")
grade = pd.Series(["A", "B", "A", "A", "B"], name="GRADE")
answer = pd.crosstab(gender, grade, margins=True)
print(answer)
assert answer.loc["All", "All"] == 5
Expected output
GRADE A B All
GENDER
F 1 2 3
M 2 0 2
All 3 2 5
Practice the pd.crosstab() examples interactively directly in your browser:
Reference: Pandas crosstab() documentation.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.