When working with missing data in Pandas, you will quickly encounter two methods that appear to do the same thing: .isna() and .isnull(). This naturally raises the question of whether they behave differently and which one you should use in your code.
This guide gives you a definitive answer, explains the historical reasons behind having two names, and shows practical patterns for working with missing values effectively.
They Are Identical
In Pandas, .isna() and .isnull() are exact aliases. They point to the same underlying function and produce identical results in every situation. There is no difference in behavior, performance, or edge-case handling:
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [1, np.nan, 3, None]})
print(df['A'].isna().equals(df['A'].isnull()))Output:
TrueThis is not a coincidence or an approximation. Internally, one is literally defined as an alias for the other in the Pandas source code.
Why Do Two Names Exist?
Pandas provides both methods to accommodate users coming from different programming backgrounds:
| Method | Convention | Background |
|---|---|---|
.isna() |
Python / NumPy | Mirrors np.isnan() and the pd.NA naming |
.isnull() |
R language | Mirrors R's is.null() function |
Early versions of Pandas leaned toward the R-style .isnull() naming. The .isna() variant was introduced later to align more closely with Python and NumPy conventions. Both were kept to avoid breaking existing code.
What Values Do They Detect?
Both methods detect the same set of missing value types in Pandas. This includes np.nan, Python's None, and the newer pd.NA used with Pandas nullable types:
import pandas as pd
import numpy as np
s = pd.Series([1, np.nan, None, pd.NA, 'text'])
print(s.isna())Output:
0 False
1 True
2 True
3 True
4 False
dtype: boolThe detected missing values are:
np.nan: the standard NumPy floating-point "not a number" sentinelNone: Python's built-in null objectpd.NA: the Pandas nullable scalar introduced for nullable integer, boolean, and string types
Regular values like integers, floats, and strings are never considered missing, regardless of which method you use.
Common Usage Patterns
Beyond simply checking which values are missing, .isna() is frequently combined with aggregation and filtering methods to summarize or handle missing data across a DataFrame:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'A': [1, np.nan, 3],
'B': [np.nan, 2, 3]
})
print("Missing per column:")
print(df.isna().sum())
print("\nAny missing at all:", df.isna().any().any())
print("Total missing:", df.isna().sum().sum())
print("\nRows with missing values:")
print(df[df.isna().any(axis=1)])Output:
Missing per column:
A 1
B 1
dtype: int64
Any missing at all: True
Total missing: 2
Rows with missing values:
A B
0 1.0 NaN
1 NaN 2.0Complementary Methods: notna() and notnull()
Just as .isna() and .isnull() are aliases, their complements .notna() and .notnull() are also identical to each other. They return True for every value that is not missing:
| Check | Methods (identical) |
|---|---|
| Value is missing | .isna() / .isnull() |
| Value is present | .notna() / .notnull() |
import pandas as pd
import numpy as np
s = pd.Series([1, np.nan, 3])
print("notna():")
print(s.notna())
print("\nnotnull():")
print(s.notnull())Output:
notna():
0 True
1 False
2 True
dtype: bool
notnull():
0 True
1 False
2 True
dtype: boolThese are useful for filtering rows where a specific column has valid data:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'score': [85, np.nan, 92]
})
valid = df[df['score'].notna()]
print(valid)Output:
name score
0 Alice 85.0
2 Charlie 92.0Which One Should You Use?
The recommended choice is isna() and notna() for the following reasons:
- Python/NumPy alignment: They match the
np.isnan()andpd.NAnaming conventions used elsewhere in the ecosystem. - Modern documentation: The official Pandas documentation predominantly uses
isna()in its examples. - Semantic clarity: "NA" (not available) is a more precise description of what these methods check for than "null," which has a different meaning in many programming contexts.
df.isna().sum()
df.notna().all()
df.isnull().sum()
df.notnull().all()Quick Reference
| Goal | Recommended Method |
|---|---|
| Check for missing values | df.isna() |
| Check for present values | df.notna() |
| Count missing per column | df.isna().sum() |
| Check if any missing exist | df.isna().any().any() |
| Total missing count | df.isna().sum().sum() |
| Filter rows with missing data | df[df.isna().any(axis=1)] |
| Filter rows without missing data | df.dropna() or df[df.notna().all(axis=1)] |
Summary
.isna() and .isnull() are 100% identical in Pandas. They are exact aliases that share the same implementation and detect the same missing value types: np.nan, None, and pd.NA. The same applies to their complements, .notna() and .notnull().
For consistency with modern Python conventions and official Pandas documentation, prefer isna() and notna() throughout your codebase.
The most important thing is to pick one style and stick with it so your code remains readable and predictable.