How to Check for Infinity and NaN in Python
In data science and scientific computing, you often encounter NaN (Not a Number) and inf (Infinity). These special values can produce unexpected results or crash your program if not handled correctly.
Because NaN != NaN evaluates to True in Python, you cannot check for it using the equality operator. Specialized functions are required.
Using the math Module
Python's built-in math library provides the standard way to check scalar values.
import math
val_nan = float('nan')
val_inf = float('inf')
val_neg_inf = float('-inf')
# Check for NaN
if math.isnan(val_nan):
print("Value is NaN")
# Check for Infinity (positive or negative)
if math.isinf(val_inf):
print("Value is infinite")
# Check if value is a valid finite number
# Returns True only if NOT NaN and NOT Inf
if math.isfinite(10.5):
print("Value is a valid finite number")
Output:
Value is NaN
Value is infinite
Value is a valid finite number
Distinguishing Positive and Negative Infinity
import math
def classify_number(value):
if math.isnan(value):
return "NaN"
elif math.isinf(value):
if value > 0:
return "Positive Infinity"
else:
return "Negative Infinity"
else:
return "Finite Number"
print(classify_number(float('inf'))) # Positive Infinity
print(classify_number(float('-inf'))) # Negative Infinity
print(classify_number(float('nan'))) # NaN
print(classify_number(42.0)) # Finite Number
Output:
Positive Infinity
Negative Infinity
NaN
Finite Number
Using NumPy for Arrays
For high-performance array operations, NumPy provides vectorized checking functions.
import numpy as np
arr = np.array([1.0, 0.0, np.nan, np.inf, -np.inf, 5.0])
# Check each element for NaN
print(np.isnan(arr)) # [False False True False False False]
# Check each element for Infinity
print(np.isinf(arr)) # [False False False True True False]
# Check each element for finite values
print(np.isfinite(arr)) # [ True True False False False True]
# Filter to keep only valid numbers
clean_arr = arr[np.isfinite(arr)]
print(clean_arr) # [1. 0. 5.]
Output:
[False False True False False False]
[False False False True True False]
[ True True False False False True]
[1. 0. 5.]
Replacing Invalid Values
import numpy as np
data = np.array([1.0, np.nan, 3.0, np.inf, 5.0])
# Replace NaN with zero
data_no_nan = np.nan_to_num(data, nan=0.0)
print(data_no_nan) # [1. 0. 3. inf 5.]
# Replace both NaN and Inf
data_clean = np.nan_to_num(data, nan=0.0, posinf=999.0, neginf=-999.0)
print(data_clean) # [1. 0. 3. 999. 5.]
Output:
[1.00000000e+000 0.00000000e+000 3.00000000e+000 1.79769313e+308 5.00000000e+000]
[ 1. 0. 3. 999. 5.]
Using Pandas for DataFrames
When working with DataFrames, use Pandas functions that handle missing data robustly.
import pandas as pd
import numpy as np
# Create DataFrame with problematic values
df = pd.DataFrame({
'values': [1.0, np.nan, np.inf, -np.inf, 5.0],
'labels': ['a', 'b', 'c', 'd', 'e']
})
# Check for NaN (also catches None)
print(df['values'].isna())
# Check for Infinity
print(np.isinf(df['values']))
# Remove rows with NaN
df_no_nan = df.dropna()
# Remove rows with NaN or Inf
df_clean = df[np.isfinite(df['values'])]
print(df_clean)
Output:
0 False
1 True
2 False
3 False
4 False
Name: values, dtype: bool
0 False
1 False
2 True
3 True
4 False
Name: values, dtype: bool
values labels
0 1.0 a
4 5.0 e
Handling Mixed Data Types
import pandas as pd
import numpy as np
def sanitize_series(series):
"""Replace NaN and Inf with None for database insertion."""
result = series.copy()
# Handle numeric columns
if pd.api.types.is_numeric_dtype(series):
mask = ~np.isfinite(series.to_numpy(dtype=float, na_value=np.nan))
result[mask] = None
return result
data = pd.Series([1.0, np.nan, np.inf, 4.0])
clean_data = sanitize_series(data)
print(clean_data)
Output:
0 1.0
1 NaN
2 NaN
3 4.0
dtype: float64
Input Validation Pattern
Always validate numerical inputs before performing calculations.
import math
def safe_divide(numerator, denominator):
# Validate inputs
for name, value in [('numerator', numerator), ('denominator', denominator)]:
if not isinstance(value, (int, float)):
raise TypeError(f"{name} must be a number")
if not math.isfinite(value):
raise ValueError(f"{name} must be a finite number")
if denominator == 0:
raise ValueError("Cannot divide by zero")
return numerator / denominator
# Usage
try:
result = safe_divide(10, float('inf'))
except ValueError as e:
print(f"Invalid input: {e}")
Output:
Invalid input: denominator must be a finite number
Quick Reference
| Function | Detects | Best For |
|---|---|---|
math.isnan() | NaN only | Single scalar values |
math.isinf() | Infinity only | Single scalar values |
math.isfinite() | Valid finite numbers | Input validation |
np.isnan() | NaN in arrays | NumPy arrays |
np.isinf() | Infinity in arrays | NumPy arrays |
np.isfinite() | Finite values in arrays | Array filtering |
pd.isna() | NaN and None | Pandas DataFrames |
Summary
Use math.isfinite() to validate user input before calculations: it catches both NaN corruption and infinity overflow in a single check. For array operations, NumPy's vectorized functions provide better performance. When working with Pandas DataFrames, combine pd.isna() with np.isinf() to handle all edge cases.