Compute the weighted mean: sum each value multiplied by its weight, then divide by the total weight. Values with larger weights pull the mean toward them more than values with smaller weights. By hand, accumulate the weighted sum and total weight in a loop. With numpy, np.average(values, weights=weights) does both steps in one call.

By hand

Loop by index, accumulating w_sum += values[i] * weights[i] and total_w += weights[i] in parallel. The trace shows both running totals growing each iteration: after the last step w_sum = 270.0 and total_w = 9.0, giving mean = 270.0 / 9.0 = 30.0.

naive.py
Replay: real traced execution (multi-file project)
values  = [10, 20, 30, 40, 50]
weights = [1, 2, 3, 2, 1]
w_sum = 0.0
total_w = 0.0
for i in range(len(values)):
    w_sum = w_sum + values[i] * weights[i]
    total_w = total_w + weights[i]
mean = w_sum / total_w
print('RESULT:', round(mean, 10))
  1. values ← [10, 20, 30, 40, 50]

    1values  = [10, 20, 30, 40, 50]2weights = [1, 2, 3, 2, 1]
    values this step[10, 20, 30, 40, 50]values
  2. weights ← [1, 2, 3, 2, 1]

    1values  = [10, 20, 30, 40, 50]2weights = [1, 2, 3, 2, 1]3w_sum = 0.0
    values this step[1, 2, 3, 2, 1]weights
  3. w_sum ← 0.0

    2weights = [1, 2, 3, 2, 1]3w_sum = 0.04total_w = 0.0
    values this step0.0w_sum
  4. total_w ← 0.0

    3w_sum = 0.04total_w = 0.05for i in range(len(values)):
    values this step0.0total_w
  5. i ← 0

    4total_w = 0.05for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]
    values this step0i
  6. w_sum ← 10.0

    5for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]
    values this step0.0 10.0w_sum
  7. total_w ← 1.0

    6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]8mean = w_sum / total_w
    values this step0.0 1.0total_w
  8. i ← 1

    4total_w = 0.05for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]
    values this step0 1i
  9. w_sum ← 50.0

    5for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]
    values this step10.0 50.0w_sum
  10. total_w ← 3.0

    6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]8mean = w_sum / total_w
    values this step1.0 3.0total_w
  11. i ← 2

    4total_w = 0.05for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]
    values this step1 2i
  12. w_sum ← 140.0

    5for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]
    values this step50.0 140.0w_sum
  13. total_w ← 6.0

    6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]8mean = w_sum / total_w
    values this step3.0 6.0total_w
  14. i ← 3

    4total_w = 0.05for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]
    values this step2 3i
  15. w_sum ← 220.0

    5for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]
    values this step140.0 220.0w_sum
  16. total_w ← 8.0

    6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]8mean = w_sum / total_w
    values this step6.0 8.0total_w
  17. i ← 4

    4total_w = 0.05for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]
    values this step3 4i
  18. w_sum ← 270.0

    5for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]
    values this step220.0 270.0w_sum
  19. total_w ← 9.0

    6    w_sum = w_sum + values[i] * weights[i]7    total_w = total_w + weights[i]8mean = w_sum / total_w
    values this step8.0 9.0total_w
  20. for i in range(len(values)):

    4total_w = 0.05for i in range(len(values)):6    w_sum = w_sum + values[i] * weights[i]
  21. mean ← 30.0

    7    total_w = total_w + weights[i]8mean = w_sum / total_w9print('RESULT:', round(mean, 10))
    values this step30.0mean
  22. stdout ← RESULT: 30.0

    8mean = w_sum / total_w9print('RESULT:', round(mean, 10))
    values this stepRESULT: 30.0stdout

With the library

np.average(values, weights=weights) computes the weighted sum and divides by the total weight in one vectorised call. float() converts the numpy scalar to a plain Python float before printing.

library.py
import numpy as np
from dalib.display import set_display
set_display()

values  = [10, 20, 30, 40, 50]
weights = [1, 2, 3, 2, 1]
wmean = float(np.average(values, weights=weights))
print('np.average:', wmean)
print('RESULT:', round(wmean, 10))
np.average: 30.0
RESULT: 30.0

Implementation notes

  • When all weights are equal, the weighted mean reduces to the arithmetic mean. With weights=[1,1,1,1,1] on this data the result would be 30.0 — the same answer, because the values are symmetric around 30.
  • np.average raises ZeroDivisionError if the weights sum to zero; the naive half has the same failure mode at mean = w_sum / total_w.
  • Cross-reference: arithmetic-mean (this chapter) for the equal-weight special case and the balance-point property.