Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
World desk3 min

How to Create Pandas Crosstab Percentages in Python

Use pd.crosstab(normalize=...) to calculate row, column, or whole-table percentages in Python. Learn what the proportions mean and when margins or aggregation change the result.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use pd.crosstab() with its normalize argument to calculate percentages instead of counts. Choose normalize="index" for percentages within each row, normalize="columns" for percentages within each column, or normalize="all" for each cell’s share of the whole table. Pandas returns proportions such as 0.25; multiply by 100 if you need numeric values on a 0–100 scale.

Choose the denominator that answers your question

A crosstab can show several different kinds of percentage. The table’s rows and columns may look identical in each case, but the denominator changes what each cell means. Pandas documents these normalization options in its crosstab API reference and cross-tabulation guide.

As an Amazon Associate I earn from qualifying purchases.

Setting Denominator Interpretation
normalize="index" The total for each row Within each row category, how observations are distributed across the columns.
normalize="columns" The total for each column Within each column category, how observations are distributed across the rows.
normalize="all" or normalize=True The total across the entire table Each cell’s share of all observations.

For example, if rows represent customer groups and columns represent outcomes, row normalization answers “what outcomes occurred within each group?” Column normalization answers “which groups contributed to each outcome?” Overall normalization answers “what share of all records is in this group-and-outcome combination?” State the denominator in the table title, labels, or explanation so readers do not mistake one conditional percentage for another.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Create row, column, and overall percentages

Assuming df is a pandas DataFrame with categorical columns named group and outcome, use the named normalization option that matches the denominator you want:

import pandas as pd

# Distribution of outcomes within each group
row_pct = pd.crosstab(df["group"], df["outcome"], normalize="index")

# Distribution of groups within each outcome
column_pct = pd.crosstab(df["group"], df["outcome"], normalize="columns")

# Share of the full dataset in each group-and-outcome cell
overall_share = pd.crosstab(df["group"], df["outcome"], normalize="all")

With row normalization, each nonempty row sums to 1; with column normalization, each nonempty column sums to 1; with overall normalization, the table’s values sum to 1. These are proportions, not numbers from 0 to 100. The named strings make the selected denominator explicit in code; the API also accepts numeric and boolean forms.

Convert proportions to numeric percentages

If the next calculation or export needs percentage values on a 0–100 scale, multiply the normalized DataFrame by 100:

row_pct_100 = row_pct.mul(100)

For instance, a proportion of 0.25 becomes 25.0. This changes the stored numeric scale; it does not add a percent sign. If the values will be presented to readers, label them as percentages and make the denominator clear.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Add totals with margins

Set margins=True to include an All row and column. Use margins_name to choose a clearer label, such as Total:

table = pd.crosstab(
    df["group"],
    df["outcome"],
    normalize="index",
    margins=True,
    margins_name="Total",
)

Pandas normalizes margin values too. Their meaning depends on the selected normalization, so inspect the resulting totals and confirm they match the denominator you intend to report.

Know when a crosstab is counting versus aggregating

With no values argument, pd.crosstab() produces a frequency table. If you supply values, you must also supply aggfunc; pandas then aggregates those values for each category combination. That is not automatically a percentage of observations. Before describing an aggregate as a percentage, define the numerator and denominator that make it meaningful.

For workflows centered on numeric aggregation or reshaping rather than a simple frequency table, pandas.pivot_table may be a better fit.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Check missing data and category behavior

  • Missing categories: Decide whether missing values should count as a category before interpreting the percentages. The dropna argument defaults to True; the API describes it as excluding columns whose entries are all NA. This is distinct from choosing a normalization denominator.
  • Unobserved categories: Categorical inputs may include categories with no observed instances, which can affect the shape of the output. Check the table before assuming every displayed category has records.
  • Unexpectedly empty output: Pandas documents that an empty DataFrame can result when the inputs have no overlapping indexes. Check that the input Series or columns align and that the categories are what you expect.

These behaviors are described in the pandas.crosstab API reference.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.