Return the harmonic mean of data. The harmonic mean is the reciprocal of the arithmetic mean of the reciprocals of the data. It can be used for averaging ratios or rates, for example speeds. Suppose a car travels 40 km/hr for 5 km and then speeds-up to 60 km/hr for another 5 k
(data, weights=None)
| 262 | |
| 263 | |
| 264 | def harmonic_mean(data, weights=None): |
| 265 | """Return the harmonic mean of data. |
| 266 | |
| 267 | The harmonic mean is the reciprocal of the arithmetic mean of the |
| 268 | reciprocals of the data. It can be used for averaging ratios or |
| 269 | rates, for example speeds. |
| 270 | |
| 271 | Suppose a car travels 40 km/hr for 5 km and then speeds-up to |
| 272 | 60 km/hr for another 5 km. What is the average speed? |
| 273 | |
| 274 | >>> harmonic_mean([40, 60]) |
| 275 | 48.0 |
| 276 | |
| 277 | Suppose a car travels 40 km/hr for 5 km, and when traffic clears, |
| 278 | speeds-up to 60 km/hr for the remaining 30 km of the journey. What |
| 279 | is the average speed? |
| 280 | |
| 281 | >>> harmonic_mean([40, 60], weights=[5, 30]) |
| 282 | 56.0 |
| 283 | |
| 284 | If ``data`` is empty, or any element is less than zero, |
| 285 | ``harmonic_mean`` will raise ``StatisticsError``. |
| 286 | |
| 287 | """ |
| 288 | if iter(data) is data: |
| 289 | data = list(data) |
| 290 | |
| 291 | errmsg = 'harmonic mean does not support negative values' |
| 292 | |
| 293 | n = len(data) |
| 294 | if n < 1: |
| 295 | raise StatisticsError('harmonic_mean requires at least one data point') |
| 296 | elif n == 1 and weights is None: |
| 297 | x = data[0] |
| 298 | if isinstance(x, (numbers.Real, Decimal)): |
| 299 | if x < 0: |
| 300 | raise StatisticsError(errmsg) |
| 301 | return x |
| 302 | else: |
| 303 | raise TypeError('unsupported type') |
| 304 | |
| 305 | if weights is None: |
| 306 | weights = repeat(1, n) |
| 307 | sum_weights = n |
| 308 | else: |
| 309 | if iter(weights) is weights: |
| 310 | weights = list(weights) |
| 311 | if len(weights) != n: |
| 312 | raise StatisticsError('Number of weights does not match data size') |
| 313 | _, sum_weights, _ = _sum(w for w in _fail_neg(weights, errmsg)) |
| 314 | |
| 315 | try: |
| 316 | data = _fail_neg(data, errmsg) |
| 317 | T, total, count = _sum(w / x if w else 0 for w, x in zip(weights, data)) |
| 318 | except ZeroDivisionError: |
| 319 | return 0 |
| 320 | |
| 321 | if total <= 0: |