Central Tendency
Weighted Mean
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.
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))
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]valuesweights ← [1, 2, 3, 2, 1]
1values = [10, 20, 30, 40, 50]2weights = [1, 2, 3, 2, 1]3w_sum = 0.0values this step[1, 2, 3, 2, 1]weightsw_sum ← 0.0
2weights = [1, 2, 3, 2, 1]3w_sum = 0.04total_w = 0.0values this step0.0w_sumtotal_w ← 0.0
3w_sum = 0.04total_w = 0.05for i in range(len(values)):values this step0.0total_wi ← 0
4total_w = 0.05for i in range(len(values)):6 w_sum = w_sum + values[i] * weights[i]values this step0iw_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_sumtotal_w ← 1.0
6 w_sum = w_sum + values[i] * weights[i]7 total_w = total_w + weights[i]8mean = w_sum / total_wvalues this step0.0 → 1.0total_wi ← 1
4total_w = 0.05for i in range(len(values)):6 w_sum = w_sum + values[i] * weights[i]values this step0 → 1iw_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_sumtotal_w ← 3.0
6 w_sum = w_sum + values[i] * weights[i]7 total_w = total_w + weights[i]8mean = w_sum / total_wvalues this step1.0 → 3.0total_wi ← 2
4total_w = 0.05for i in range(len(values)):6 w_sum = w_sum + values[i] * weights[i]values this step1 → 2iw_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_sumtotal_w ← 6.0
6 w_sum = w_sum + values[i] * weights[i]7 total_w = total_w + weights[i]8mean = w_sum / total_wvalues this step3.0 → 6.0total_wi ← 3
4total_w = 0.05for i in range(len(values)):6 w_sum = w_sum + values[i] * weights[i]values this step2 → 3iw_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_sumtotal_w ← 8.0
6 w_sum = w_sum + values[i] * weights[i]7 total_w = total_w + weights[i]8mean = w_sum / total_wvalues this step6.0 → 8.0total_wi ← 4
4total_w = 0.05for i in range(len(values)):6 w_sum = w_sum + values[i] * weights[i]values this step3 → 4iw_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_sumtotal_w ← 9.0
6 w_sum = w_sum + values[i] * weights[i]7 total_w = total_w + weights[i]8mean = w_sum / total_wvalues this step8.0 → 9.0total_wfor i in range(len(values)):
4total_w = 0.05for i in range(len(values)):6 w_sum = w_sum + values[i] * weights[i]mean ← 30.0
7 total_w = total_w + weights[i]8mean = w_sum / total_w9print('RESULT:', round(mean, 10))values this step30.0meanstdout ← 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.
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.averageraisesZeroDivisionErrorif the weights sum to zero; the naive half has the same failure mode atmean = w_sum / total_w.- Cross-reference:
arithmetic-mean(this chapter) for the equal-weight special case and the balance-point property.