Introduction
To count NaN values in a pandas DataFrame column, use df['column'].isna().sum(). This returns the number of missing values in that column. For the entire DataFrame, use df.isna().sum() to get NaN counts per column, or df.isna().sum().sum() for the total count across all columns. The isna() method (alias isnull()) creates a boolean mask where True indicates a NaN value, and sum() counts the True values.
Count NaN in a Single Column
1import pandas as pd
2import numpy as np
3
4df = pd.DataFrame({
5 'name': ['Alice', 'Bob', None, 'Diana', 'Eve'],
6 'age': [25, np.nan, 30, np.nan, 28],
7 'salary': [50000, 60000, np.nan, 55000, np.nan]
8})
9
10# Count NaN in one column
11nan_count = df['age'].isna().sum()
12print(nan_count) # 2
13
14# Alternative: isnull() is an alias for isna()
15nan_count = df['age'].isnull().sum()
16print(nan_count) # 2
Count NaN Per Column
1# NaN count for every column
2print(df.isna().sum())
3# name 1
4# age 2
5# salary 2
6# dtype: int64
7
8# Only columns with NaN values
9nan_counts = df.isna().sum()
10print(nan_counts[nan_counts > 0])
11# name 1
12# age 2
13# salary 2
14# dtype: int64
Count NaN for the Entire DataFrame
1# Total NaN across all columns
2total_nan = df.isna().sum().sum()
3print(total_nan) # 5
4
5# Alternative: count all values, then count non-NaN
6total_nan = df.size - df.count().sum()
7print(total_nan) # 5
NaN Percentage
1# Percentage of NaN per column
2nan_pct = df.isna().mean() * 100
3print(nan_pct)
4# name 20.0
5# age 40.0
6# salary 40.0
7# dtype: float64
8
9# Formatted output
10for col in df.columns:
11 pct = df[col].isna().mean() * 100
12 count = df[col].isna().sum()
13 print(f"{col}: {count} NaN ({pct:.1f}%)")
14# name: 1 NaN (20.0%)
15# age: 2 NaN (40.0%)
16# salary: 2 NaN (40.0%)
Count Non-NaN Values
1# count() returns non-NaN values per column
2print(df.count())
3# name 4
4# age 3
5# salary 3
6# dtype: int64
7
8# For a single column
9non_nan = df['age'].count()
10print(non_nan) # 3
11
12# Equivalently
13non_nan = df['age'].notna().sum()
14print(non_nan) # 3
NaN Count Per Row
1# How many NaN values in each row
2print(df.isna().sum(axis=1))
3# 0 0
4# 1 1
5# 2 2
6# 3 1
7# 4 1
8# dtype: int64
9
10# Rows with any NaN
11rows_with_nan = df[df.isna().any(axis=1)]
12print(len(rows_with_nan)) # 4 rows have at least one NaN
Using info() for a Quick Overview
1df.info()
2# <class 'pandas.core.frame.DataFrame'>
3# RangeIndex: 5 entries, 0 to 4
4# Data columns (total 3 columns):
5# # Column Non-Null Count Dtype
6# --- ------ -------------- -----
7# 0 name 4 non-null object
8# 1 age 3 non-null float64
9# 2 salary 3 non-null float64
10# dtypes: float64(2), object(1)
11
12# Non-Null Count shows how many values are NOT NaN
13# 5 total - 3 non-null = 2 NaN for 'age'
Using describe() for NaN Awareness
1print(df.describe())
2# age salary
3# count 3.000000 3.000000
4# mean 27.666667 55000.000000
5# ...
6
7# The 'count' row shows non-NaN values
8# 'age' has count=3 out of 5 rows → 2 NaN
Counting Specific Missing Value Types
1# NaN is not the only "missing" value
2df2 = pd.DataFrame({
3 'col': [1, np.nan, None, '', 0, pd.NaT, 'N/A']
4})
5
6# isna() catches NaN, None, and NaT
7print(df2['col'].isna().sum()) # 3 (NaN, None, NaT)
8
9# Empty strings and 'N/A' are NOT considered NaN
10# Count those separately
11empty_count = (df2['col'] == '').sum()
12na_string_count = (df2['col'] == 'N/A').sum()
13
14# Replace custom missing indicators, then count
15df2['col'] = df2['col'].replace({'': np.nan, 'N/A': np.nan, 0: np.nan})
16print(df2['col'].isna().sum()) # 6
Common Pitfalls
Confusing count() with len(): df['col'].count() returns the number of non-NaN values. len(df['col']) returns the total number of rows including NaN. To get NaN count: len(df['col']) - df['col'].count() or simply df['col'].isna().sum().
Empty strings are not NaN: isna() detects np.nan, None, and pd.NaT but NOT empty strings (''), zeros (0), or placeholder text ('N/A', 'null'). Use df['col'].replace('', np.nan) before counting if empty strings represent missing data in your dataset.
NaN comparisons with ==: np.nan == np.nan is False in Python. Never use df['col'] == np.nan to find missing values — it returns all False. Always use df['col'].isna() or pd.isna(df['col']).
Using sum() without isna() first: df['col'].sum() adds up the numeric values (skipping NaN). It does not count NaN. You need df['col'].isna().sum() — first create the boolean mask, then sum it.
Integer columns silently converting to float: When a column with integer data has NaN values, pandas converts the entire column to float64 because standard int does not support NaN. Use pd.Int64Dtype() (nullable integer) to keep integer type: df['col'] = df['col'].astype('Int64').
Summary
Use df['col'].isna().sum() to count NaN in a single column
Use df.isna().sum() for NaN counts per column, df.isna().sum().sum() for total
Use df.isna().mean() * 100 for NaN percentage per column
Use df.isna().sum(axis=1) to count NaN per row
isna() and isnull() are identical — use either one consistently