Skip to main content

Python NumPy: How to Fix "RuntimeWarning: divide by zero encountered in log10"

When performing logarithmic calculations in NumPy using numpy.log10() (or numpy.log(), numpy.log2()), you might encounter a RuntimeWarning: divide by zero encountered in log10. This warning specifically arises when you attempt to calculate the logarithm of zero. Mathematically, the logarithm of zero is undefined (it tends towards negative infinity). NumPy handles this by returning -np.inf and issuing the warning to alert you to this mathematical edge case.

This guide will clearly explain why taking the log10 of zero triggers this RuntimeWarning, demonstrate how to reproduce it, and provide robust solutions, primarily focusing on using numpy.errstate() or numpy.seterr() to manage NumPy's error handling for such operations, or by selectively applying the logarithm using the where parameter.

Understanding the Warning: Logarithm of Zero

The logarithm function log_b(x) asks, "To what power must I raise the base b to get x?".

  • For log10(0), we're asking, "To what power must I raise 10 to get 0?"
  • Mathematically, there is no such real number. As y approaches negative infinity (-inf), 10^y approaches zero from the positive side.
  • Thus, log10(0) is undefined but tends towards -inf.

NumPy's np.log10() function, when encountering a 0 in the input array:

  1. Returns -np.inf (negative infinity) for that element.
  2. Issues a RuntimeWarning: divide by zero encountered in log10. The "divide by zero" part of the message is a bit of a misnomer in the direct sense for log10 but reflects the underlying numerical instability and the limit approaching infinity.

The same applies to np.log() (natural logarithm, base e) and np.log2() (base 2 logarithm). Taking the logarithm of a negative number will result in np.nan and potentially an "invalid value encountered" warning.

Reproducing the Warning with numpy.log10()

import numpy as np

# Array containing zero and positive numbers
data_array = np.array([0.1, 1.0, 0.0, 10.0, 100.0, 0.0])
print(f"Original array: {data_array}")

# ⛔️ RuntimeWarning: divide by zero encountered in log10
# (This warning prints to stderr)
log_values_with_warning = np.log10(data_array)

print("Result of np.log10() (contains -inf):")
print(log_values_with_warning)

Output:

Original array: [  0.1   1.    0.   10.  100.    0. ]
Result of np.log10() (contains -inf):
[ -1. 0. -inf 1. 2. -inf]
note

The 0.0 values in data_array lead to -inf in the output and trigger the warning.

If you understand that log10(0) will result in -inf and this is an acceptable outcome for your calculations, you can temporarily suppress the warning for a specific block of code using the numpy.errstate() context manager. This is generally the safest way to manage warnings locally.

import numpy as np

# data_array defined as above
data_array = np.array([0.1, 1.0, 0.0, 10.0, 100.0, 0.0])
print(f"Original array: {data_array}")

print("Attempting log10 within np.errstate(divide='ignore'):")
# ✅ Temporarily ignore 'divide by zero' type warnings within this block
with np.errstate(divide='ignore'):
log_values_no_warning_context = np.log10(data_array)
# No warning will be printed to stderr for the operation inside this block
print(log_values_no_warning_context)

print("Attempting log10 outside errstate (default warning behavior restored):")

log_values_default_behavior = np.log10(data_array) # This would warn again
print(log_values_default_behavior)

Output:

Original array: [  0.1   1.    0.   10.  100.    0. ]
Attempting log10 within np.errstate(divide='ignore'):
[ -1. 0. -inf 1. 2. -inf]
Attempting log10 outside errstate (default warning behavior restored):
[ -1. 0. -inf 1. 2. -inf]
note

Inside the with np.errstate(divide='ignore'): block, NumPy is instructed to take no action (ignore) when a "divide by zero" type of floating-point event occurs during ufunc execution (like log10). The error handling behavior reverts to its previous state upon exiting the block.

Solution 2: Globally Ignoring the Warning with numpy.seterr() (Use with Care)

The numpy.seterr() function allows you to change NumPy's floating-point error handling behavior globally for the current Python session or until seterr() is called again.

import numpy as np

# data_array defined as above
data_array = np.array([0.1, 1.0, 0.0, 10.0, 100.0, 0.0])
print(f"Original array: {data_array}")

# Store the current error settings if you want to restore them later
old_settings = np.seterr(divide='ignore') # Ignore divide by zero, returns old settings
print("Globally ignoring 'divide by zero' warnings with np.seterr():")

log_values_seterr_ignore = np.log10(data_array)
print(log_values_seterr_ignore)

# ✅ It's good practice to restore original settings if you changed them globally
np.seterr(**old_settings) # Restore previous error handling settings
print("Error settings restored. Attempting log10 again (should warn):")
log_values_restored_behavior = np.log10(data_array) # This would warn
print(log_values_restored_behavior)

Output:

Original array: [  0.1   1.    0.   10.  100.    0. ]
Globally ignoring 'divide by zero' warnings with np.seterr():
[ -1. 0. -inf 1. 2. -inf]
Error settings restored. Attempting log10 again (should warn):
[ -1. 0. -inf 1. 2. -inf]
note

Using np.seterr() affects all subsequent NumPy operations. While it can suppress the warning, it might also hide legitimate issues in other parts of your code if not managed carefully. np.errstate() is generally preferred for localized control.

Solution 3: Conditional Calculation with the where Parameter in np.log10()

Many NumPy ufuncs, including np.log10(), accept a where parameter. This parameter takes a boolean array of the same shape as the input. The operation is only performed where the where array is True; for elements where it's False, the original value of an optional out array is used, or uninitialized memory if out is not provided (often resulting in zeros or garbage values if not careful, or np.nan if the output array's default can hold it).

To avoid log10(0), you can specify where=arr > 0. You also usually want to specify an out array initialized to a sensible default (like np.nan) for the positions where the condition is false.

import numpy as np

# data_array defined as above
data_array = np.array([0.1, 1.0, 0.0, 10.0, 100.0, 0.0])
print(f"Original array: {data_array}")

# Create an output array, initialized with NaN (or another placeholder)
output_array = np.full_like(data_array, fill_value=np.nan, dtype=np.float64)
# Ensure dtype is float to hold -inf and NaN for log results.

# ✅ Calculate log10 only where data_array > 0
# For elements where data_array <= 0, the corresponding value in output_array (np.nan) will be kept.
condition_positive = (data_array > 0)
log_values_conditional = np.log10(data_array, where=condition_positive, out=output_array)

print("Result of np.log10(arr, where=arr > 0, out=initialized_array):")
print(log_values_conditional)

Output:

Original array: [  0.1   1.    0.   10.  100.    0. ]
Result of np.log10(arr, where=arr > 0, out=initialized_array):
[-1. 0. nan 1. 2. nan]
note

This method prevents the operation that causes the warning from even occurring on the problematic values, often yielding a cleaner result (e.g., np.nan instead of -np.inf) for the non-positive inputs.

Important: Understanding the Output (-inf)

Even if you suppress the warning, np.log10(0) will still produce -np.inf. Your downstream code needs to be prepared to handle -np.inf values if they are not what you intend.

import numpy as np

# data_array defined as above
data_array = np.array([0.1, 1.0, 0.0, 10.0, 100.0, 0.0])
print(f"Original array: {data_array}")

with np.errstate(divide='ignore'):
result = np.log10(data_array)
print(f"Result with -inf values: {result}")
print(f"Is the third element -inf? {result[2] == -np.inf}")
print(f"Is the third element finite? {np.isfinite(result[2])}")
note

If -inf is not a desirable outcome, using the where parameter (Solution 3) to substitute another value (like np.nan or a very small number) for log10(0) is often a better data handling strategy.

Conclusion

The NumPy RuntimeWarning: divide by zero encountered in log10 occurs because the logarithm of zero is mathematically undefined and tends towards negative infinity. NumPy signals this by returning -np.inf and issuing a warning. To manage this:

  1. with np.errstate(divide='ignore'):: This is the recommended way to locally suppress the warning if you accept -np.inf as the result for log10(0).
  2. np.seterr(divide='ignore'): Use this for global suppression if absolutely necessary, but remember to reset it if its effect is not desired for your entire script.
  3. np.log10(arr, out=out_arr, where=arr > 0): This is the most robust solution if you want to avoid computing log10(0) altogether and instead have a different value (like np.nan) in those positions.

Understanding the mathematical context and NumPy's error handling mechanisms allows you to process logarithmic computations cleanly and effectively.