statistics: harmonic_mean() Returns 0 If Any Value Is 0 (tested)
statistics.harmonic_mean() is the right tool for averaging rates and ratios (speeds, price-per-unit, etc.), and its docstring only warns that negative values raise an error. We measured what a zero in the data actually does, since harmonic mean's definition involves dividing by each value -- and a single zero overrides every other value in the dataset.
1. A single zero among large values makes the whole result zero
import statistics as st
print(st.harmonic_mean([5, 0, 10]))
print(st.harmonic_mean([1, 2, 3]))
0
1.6363636363636365
Measured: harmonic_mean([5, 0, 10]) returns exactly 0 -- not an error, not a value influenced partly by the 5 and 10. For comparison, the same-shaped data with no zero ([1, 2, 3]) returns the expected nonzero harmonic mean.
2. This holds no matter how large the other values are, or how many zeros
import statistics as st
print(st.harmonic_mean([1_000_000, 0, 1_000_000]))
print(st.harmonic_mean([0, 0, 0]))
0
0
Measured: even with two enormous values of 1,000,000 alongside a single 0, the result is still exactly 0 -- there's no averaging-away of a single zero outlier. This matches the mathematical definition (harmonic mean is the reciprocal of the mean of reciprocals, and 1/0 is undefined/infinite, which the implementation resolves to a result of 0 rather than raising), but it's easy to assume zero would be treated like any other low value, or would raise like negative values do.
3. Negative values raise an explicit error -- zero does not, even though both break the math
import statistics as st
try:
st.harmonic_mean([1, 2, -3])
except Exception as e:
print("raises:", type(e).__name__, e)
print("zero result:", st.harmonic_mean([1, 2, 0]))
raises: StatisticsError harmonic mean does not support negative values
zero result: 0
Measured: harmonic_mean() explicitly guards against negative values with a named StatisticsError, but applies no equivalent guard for zero -- it silently computes a mathematically defined but easy-to-miss answer instead. A speed/rate-averaging pipeline that filters out negative sensor readings (correctly) but doesn't also filter zero readings (e.g. a vehicle stopped for one measurement interval, a sensor reading that rounds to 0) will see its entire average silently collapse to 0 the moment a single zero appears in otherwise-healthy data, with no exception to catch and no warning in the output. If zero values are a legitimate possibility in your data and shouldn't dominate the average, filter them out (or substitute a very small nonzero floor) before calling harmonic_mean().
Frequently asked questions
What does statistics.harmonic_mean() return if one value in the data is zero?
0 -- we measured harmonic_mean([5, 0, 10]) returning exactly 0, regardless of how large the other values are. A single zero makes the entire result zero, with no error or warning.
Does statistics.harmonic_mean() raise an error for zero values like it does for negative values?
No -- we confirmed harmonic_mean() raises StatisticsError for any negative value ('harmonic mean does not support negative values'), but applies no such guard for zero. Zero is silently accepted and produces a result of 0.
Why does one zero value dominate the entire harmonic mean?
Harmonic mean is defined as the reciprocal of the average of the reciprocals of the data. A zero's reciprocal is undefined/infinite, and Python's implementation resolves this case by returning 0 for the whole result rather than raising, no matter what the other values are.
How do I average rates with statistics.harmonic_mean() when some values might be zero?
Filter out zero values before calling harmonic_mean(), or substitute a small nonzero floor if a zero reading is a data artifact rather than a true zero rate -- we confirmed the function provides no built-in option to ignore or weight down zeros.
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in statistics module: called harmonic_mean() on data containing exactly one zero alongside large nonzero values, on all-zero data, and compared to the explicit error raised for a negative value. PlainHeaders is our extension; Python's statistics module is built in.