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')
if math.isnan(val_nan):
print("Value is NaN")
if math.isinf(val_inf):
print("Value is infinite")
if math.isfinite(10.5):
print("Value is a valid finite number")Output:
Value is NaN
Value is infinite
Value is a valid finite numberDistinguishing 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 NumberOutput:
Positive Infinity
Negative Infinity
NaN
Finite NumberUsing 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])
print(np.isnan(arr)) # [False False True False False False]
print(np.isinf(arr)) # [False False False True True False]
print(np.isfinite(arr)) # [ True True False False False True]
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])
data_no_nan = np.nan_to_num(data, nan=0.0)
print(data_no_nan) # [1. 0. 3. inf 5.]
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
df = pd.DataFrame({
'values': [1.0, np.nan, np.inf, -np.inf, 5.0],
'labels': ['a', 'b', 'c', 'd', 'e']
})
print(df['values'].isna())
print(np.isinf(df['values']))
df_no_nan = df.dropna()
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 eHandling 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()
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: float64Input Validation Pattern
Always validate numerical inputs before performing calculations.
import math
def safe_divide(numerator, denominator):
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
try:
result = safe_divide(10, float('inf'))
except ValueError as e:
print(f"Invalid input: {e}")Output:
Invalid input: denominator must be a finite numberQuick 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.