Pandas Count Unique Values In Column

10 min read

Counting unique values in a column with pandas is a common data analysis task that helps you understand the variety, distribution, and quality of your data. Whether you are working with customer names, product categories, status codes, or categorical variables, knowing how many distinct values exist in a pandas column is one of the fastest ways to explore a dataset.

Introduction to Counting Unique Values in pandas

In pandas, a column is usually represented as a Series, and each row contains a value from that column. Counting unique values means identifying how many different values appear in that column The details matter here. Took long enough..

As an example, if a column contains these values:

["apple", "banana", "apple", "orange", "banana"]

The unique values are:

["apple", "banana", "orange"]

So, the count of unique values is 3.

Pandas provides several useful methods for counting unique values, including:

  • .nunique()
  • .value_counts()
  • groupby().nunique()
  • .drop_duplicates()

Each method is useful in slightly different situations Not complicated — just consistent..

Count Unique Values in a pandas Column with .nunique()

The most direct way to count unique values in a pandas column is using the .nunique() method That's the part that actually makes a difference..

import pandas as pd

df = pd.DataFrame({
    "fruit": ["apple", "banana", "apple", "orange", "banana", "apple"]
})

unique_count = df["fruit"].nunique()

print(unique_count)

Output:

3

The .nunique() method returns the number of distinct values in the column.

Basic Syntax

df["column_name"].nunique()

Where:

  • df is your pandas DataFrame
  • "column_name" is the column you want to analyze

Example with Multiple Columns

You can also count unique values across multiple columns:

unique_counts = df["fruit"].nunique()

Or for multiple columns:

unique_counts = df[["fruit", "color"]].nunique()

Output may look like this:

fruit      3
color      4
Name: nunique, dtype: int64

Count Unique Values Including or Excluding Missing Values

By default, .Practically speaking, nunique() counts missing values such as NaN as one unique value. This behavior is important to understand because missing data can affect your results.

df = pd.DataFrame({
    "status": ["active", "inactive", "active", None, "pending", None]
})

print(df["status"].nunique())

Output:

4

The result is 4 because pandas counts:

["active", "inactive", "pending", NaN]

If you want to exclude missing values, use the dropna parameter:

print(df["status"].nunique(dropna=True))

Output:

3

Common options are:

df["column"].nunique(dropna=False)
df["column"].nunique(dropna=True)

Use:

  • dropna=False when you want missing values counted as a category
  • dropna=True when you only want non-missing values

Count Unique Values and Their Frequencies with .value_counts()

While .nunique() only returns the number of unique values, .value_counts() shows how often each unique value appears Still holds up..

df = pd.DataFrame({
    "category": ["red", "blue", "red", "green", "blue", "red"]
})

print(df["category"].value_counts())

Output:

red     3
blue    2
green   1
Name: category, dtype: int64

This is useful when you want to know both:

  1. How many unique values exist
  2. How frequently each value appears

To get only the number of unique values from .value_counts(), use len():

unique_count = len(df["category"].value_counts())

print(unique_count)

Output:

3

You can also count unique values while ignoring missing values:

unique_count = len(df["category"].value_counts(dropna=True))

Difference Between .nunique() and .value_counts()

It is helpful to understand the difference between these two methods Not complicated — just consistent. Took long enough..

Method Purpose Example Output
.nunique() Counts how many unique values exist 5
.value_counts() Counts how often each unique value appears A: 10, B: 5, C: 2

Example:

df = pd.DataFrame({
    "city": ["London", "Paris", "London", "Berlin", "Paris"]
})

print(df["city"].nunique())

Output:

3
print(df["city"].value_counts())

Output:

London    2
Paris     2
Berlin    1
Name: city, dtype: int64

Use .nunique() when you only need the count. Use .value_counts() when you need a frequency distribution Which is the point..

Count Unique Values in a DataFrame Column

To count unique values in a single column:

unique_count = df["column_name"].nunique()
print(unique_count)

To count unique values for all object or categorical columns:

object_columns = df.select_dtypes(include=["object", "category"]).columns

for col in object_columns:
    print(col, df[col].nunique())

You can also create a summary table:

unique_summary = df[object_columns].nunique()

print(unique_summary)

Example output:

name      500
city       12
status     4
product   120
dtype: int64

This is a useful first step during data exploration.

Count Unique Values in Multiple Columns

If you want to count unique values for several columns at once, select the columns and apply .nunique().

columns_to_check = ["city", "status", "product"]

unique_counts = df[columns_to_check].nunique()

print(unique_counts)

Output:

city      12
status     4
product  120
Name: nunique, dtype: int64

To convert the result into a more readable table:

unique_summary = pd.DataFrame({
    "column_name": columns_to_check,
    "unique_count": df[columns_to_check].nunique().values
})

print(unique_summary)

Output:

  column_name  unique_count
0        city              12
1      status               4
2     product            120

Count Unique Values Across the Entire DataFrame

To get a quick overview of cardinality for every column in your DataFrame, call .nunique() directly on the DataFrame object. By default, this operates column-wise (axis=0) Nothing fancy..

unique_counts = df.nunique()

print(unique_counts)

Output:

id           1000
name          950
city           12
status          4
product       120
signup_date   365
dtype: int64

This instantly highlights high-cardinality columns (like id or name) versus low-cardinality categorical columns (like status), which is critical for deciding encoding strategies or identifying potential primary keys.

Controlling NaN Handling Globally

The dropna parameter behaves identically on the DataFrame level. Setting dropna=False counts NaN as a distinct category, which is useful for auditing data completeness And that's really what it comes down to. Simple as that..

# Count NaN as a unique value
unique_with_nan = df.nunique(dropna=False)

print(unique_with_nan)

Count Unique Combinations Across Multiple Columns

Often, you need to know how many unique records exist based on a subset of columns—for example, unique users per city, or unique product-status pairs. groupby().Use .Because of that, drop_duplicates() on the column subset followed by len(), or use . ngroups And that's really what it comes down to. Surprisingly effective..

Method 1: drop_duplicates (Intuitive & Flexible)

# Unique combinations of city and status
unique_pairs = df[["city", "status"]].drop_duplicates()

count = len(unique_pairs)
print(f"Unique city/status combinations: {count}")

# Inspect the actual combinations
print(unique_pairs)

Output:

Unique city/status combinations: 15
      city status
0   London  active
1    Paris  active
3  Berlin  active
4   London  pending
...

Method 2: groupby().ngroups (Performant for Large Data)

For very large DataFrames, groupby avoids the overhead of creating a deduplicated copy of the data Worth knowing..

count = df.groupby(["city", "status"]).ngroups
print(count)

Output:

15

Method 3: value_counts() on Multiple Columns (Frequency of Combinations)

If you need the frequency of each combination rather than just the count of combinations, pass a list of columns to .value_counts().

combo_counts = df[["city", "status"]].value_counts()

print(combo_counts)

Output:

city    status
London  active      45
Paris   active      38
Berlin  active      22
London  pending     12
Paris   pending      8
...
dtype: int64

This returns a Series with a MultiIndex, making it easy to filter for the most (or least) common segments That's the part that actually makes a difference..

Performance Considerations

  • .nunique() vs len(.unique()): Always prefer .nunique(). It is implemented in Cython and returns a scalar integer immediately. df[col].unique() materializes the entire array of unique values in memory before len() counts them, which is significantly slower and memory-intensive for high-cardinality columns.
  • Approximate Counts: For massive datasets (millions of rows) where exact precision is not required, consider probabilistic algorithms like HyperLogLog (available via libraries like datasketch or pyspark.sql.functions.approx_count_distinct). Pandas does not have a built-in approximate distinct count.

Summary Cheat Sheet

Task Recommended Syntax Returns
Unique count (Series) s.nunique() int
Unique count + NaN s.nunique(dropna=False) int
Frequency table s.value_counts() Series
Unique count (DataFrame) df.nunique() Series (per column)
Unique row combos (count) `df[['A', 'B']].drop_duplicates().

Beyond the elementary patterns displayed earlier, there are several nuanced scenarios that often arise when counting distinct elements in a pandas structure Most people skip this — try not to. Still holds up..

Managing missing values
When NaN entries are present, the default behavior of nunique() excludes them unless the dropna flag is set to False. This allows you to decide whether a missing entry should contribute to the distinct count. For example:

s = pd.Series([1, 2, 2, None, 3, None])
print(s.nunique())               # 3  (NaNs are ignored)
print(s.nunique(dropna=False))   # 4  (NaNs are counted as a separate level)

The same argument applies to value_counts(), which can be instructed to treat NaN as a regular category by passing dropna=False Less friction, more output..

Aggregating across multiple columns
If you need the distinct count for a combination of columns, you can either rely on drop_duplicates() on a sliced view of the frame or employ groupby with size(). The latter is often more memory‑efficient because it works directly on the original index without materialising a new DataFrame And that's really what it comes down to. But it adds up..

# Count distinct (city, status) pairs using groupby
pair_counts = df.groupby(["city", "status"]).size()
print(pair_counts)

pair_counts yields a Series whose index is a MultiIndex of the unique pairs and whose values represent how many times each pair occurs. This approach scales well to millions of rows, as the grouping operation is performed in‑place Surprisingly effective..

Row‑wise distinctness
Sometimes the interest lies in how many unique values appear across an entire row rather than within a single column. The nunique(axis=1) signature lets you compute this directly:

row_uniques = df.nunique(axis=1)
print(row_uniques)

Each entry in row_uniques tells you the number of different non‑null values present in the corresponding row.

Memory‑friendly tricks
High‑cardinality columns can inflate memory usage. Converting object‑type columns that have a limited set of values to the category dtype often reduces the footprint dramatically and can speed up nunique() because the underlying codes are smaller integers And it works..

df["city"] = df["city"].astype("category")
df["status"] = df["status"].astype("category")

After conversion, calling nunique() will still return the correct count, but the operation will be faster and use less RAM.

Choosing the right tool

  • Exact counts for modest‑size datanunique() (or len(df[cols].drop_duplicates())) is straightforward and fast enough for most analytics workloads.
  • Exact counts on very large tablesgroupby([...]).ngroups avoids the extra copy that drop_duplicates() would create.
  • Frequency distributionvalue_counts() (with or without dropna=False) provides a full breakdown of how often each distinct combination appears.
  • Row‑level distinctnessnunique(axis=1) delivers per‑row uniqueness without any reshaping.

Practical checklist

  1. Decide whether missing values should be counted.
  2. Choose a method that matches the required granularity (column vs. row vs. combination).
  3. For massive datasets, prefer the grouping‑based approach to keep memory overhead low.
  4. Convert high‑cardinality columns to category when feasible.

Conclusion

Counting distinct elements in pandas can be accomplished through a handful of idiomatic patterns, each meant for a specific need. size() become indispensable. But ). ngroups offers a scalable alternative for huge frames. ).The nunique() method remains the most direct way to obtain a simple count, while groupby(...Practically speaking, when you need more than a raw total—such as the distribution of each unique combination—value_counts()orgroupby(... By understanding the trade‑offs in memory usage, speed, and the handling of missing data, you can select the optimal technique for any analytical scenario, ensuring both correctness and efficiency.

Out the Door

Latest from Us

Handpicked

More Good Stuff

Thank you for reading about Pandas Count Unique Values In Column. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home