Counting & Uniques: value_counts, unique, nunique
value_counts() tallies how often each distinct value appears in a column, giving you an instant frequency table — the workhorse of exploratory data analysis.
Learn Counting & Uniques: value_counts, unique, nunique in our free Pandas course — a beginner-friendly interactive lesson with worked examples, a practice…
Part of the free Pandas course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Learn to count categories, turn counts into percentages with normalize=, include missing values with dropna=False, and list distinct values with unique() and nunique().
Call value_counts() on a Series and pandas counts how many times each distinct value appears, then hands back the tallies sorted from most common to least. It is the first thing analysts run on a new categorical column: one line tells you the mode, the spread, and whether any category dominates.
Two arguments make value_counts far more useful. normalize=True converts the raw counts into proportions that add up to 1 — multiply by 100 and you have percentages, perfect for "what share of customers are on each plan?" And dropna=False stops pandas from hiding the gaps: missing values appear as their own NaN row so you can see how incomplete a column really is.
When you do not need the counts, just the distinct values, reach for unique() and nunique() . unique() returns an array of the actual distinct values — useful for spotting typos and stray categories. nunique() returns a single number: how many distinct values exist. That count, called cardinality, tells you whether a column is a good candidate for the category dtype or a grouping key.
❌ Calling value_counts on a whole DataFrame by mistake
You wanted to count one column but passed the frame:
Your counts do not add up to the row total because NaN was dropped:
Quickly profile a column of responses for an EDA report.
Lesson complete — you can profile any column!
You can build frequency tables with value_counts() , switch to shares with normalize=True , expose gaps with dropna=False , and measure distinctness with unique() and nunique() .
🚀 Up next: Filtering with query() — write readable filters as plain-English strings.
Practice quiz
What does s.value_counts() return?
- The number of rows
- A frequency table of how often each value appears
- The unique values only
- The column mean
Answer: A frequency table of how often each value appears. value_counts() tallies each distinct value's frequency.
How is value_counts() ordered by default?
- Alphabetically
- By the index labels
- From most frequent to least frequent
- Randomly
Answer: From most frequent to least frequent. It sorts descending by count, so the top row is the mode.
What does normalize=True do?
- Sorts the result
- Removes missing values
- Capitalises labels
- Converts counts to proportions that sum to 1
Answer: Converts counts to proportions that sum to 1. normalize=True returns each value's share as a fraction.
Which argument makes NaN appear as its own row?
- dropna=False
- include_na=True
- keepna=True
- na='show'
Answer: dropna=False. dropna=False stops pandas hiding the missing values.
Does value_counts() include NaN by default?
- Always
- No, it drops NaN unless told otherwise
- Only for numeric columns
- Only the first NaN
Answer: No, it drops NaN unless told otherwise. By default NaN is excluded; pass dropna=False to include it.
What does unique() return?
- A single count
- The most common value
- An array of the distinct values
- A sorted Series
Answer: An array of the distinct values. unique() lists the actual distinct values in the column.
What does nunique() return?
- The distinct values
- A frequency table
- The first value
- The count of distinct values (a single number)
Answer: The count of distinct values (a single number). nunique() reports how many distinct values exist (cardinality).
If value_counts(normalize=True) is computed with dropna=True, what is the denominator?
- Only the non-missing rows
- All rows including NaN
- Always 100
- The number of columns
Answer: Only the non-missing rows. Proportions are over non-null values unless you keep NaN in.
What is the result type of value_counts()?
- A list
- A dict
- A Series (values as index, counts as values)
- A DataFrame
Answer: A Series (values as index, counts as values). It returns a Series, so you can chain .head() or .plot.bar().
A low nunique() relative to row count suggests what?
- The data is corrupted
- Every value is unique
- There are no repeats
- Lots of repeats — a good 'category' dtype candidate
Answer: Lots of repeats — a good 'category' dtype candidate. Few distinct values among many rows means heavy repetition.