Can you average percentages? Why the average of averages lies
Predict why the average of each site's rate isn't the clinic's rate, then fix a calculation that makes that mistake.
Free course. Your Maestro, an AI, .
In the week of September 21, each site had its own no-show rate: Centro 10.1%, Angelópolis 9.8% and Cholula 17.1%. Lucía needs one figure for the whole clinic. Before you see how it's calculated, predict what this program prints.
The first program uses the week's actual appointments. The second changes one thing. Predict both. The programs print their labels in Spanish; the comments in the code tell you what they mean.
The first program uses the week's actual appointments. The second changes one thing. Predict both. The programs print their labels in Spanish; the comments in the code tell you what they mean.
Three sites of different sizes
Example 1 of 2
# Week of September 21: no-shows and active appointments for each site.
sedes = {
"Centro": {"inasistencias": 17, "en_pie": 169},
"Angelópolis": {"inasistencias": 12, "en_pie": 123},
"Cholula": {"inasistencias": 14, "en_pie": 82},
}
tasas = [s["inasistencias"] / s["en_pie"] for s in sedes.values()]
promedio_de_tasas = sum(tasas) / len(tasas)
inasistencias = sum(s["inasistencias"] for s in sedes.values())
en_pie = sum(s["en_pie"] for s in sedes.values())
tasa_clinica = inasistencias / en_pie
# Labels in Spanish: "Promedio de las tres tasas" = average of the three rates;
# "Tasa de la clínica" = the clinic's rate.
print(f"Promedio de las tres tasas: {promedio_de_tasas:.1%}")
print(f"Tasa de la clínica: {tasa_clinica:.1%}")
A guess is fine: it's kept as you wrote it, so you can compare. Only you and your Maestro see your predictions.
Example 2 of 2, opens once you explain this one
The rule: add up the top, add up the bottom, then divide
When you want the rate or the average for a big group made of smaller groups, don't average the small groups' rates. Add up the numerators, add up the denominators, and divide at the end. That way each appointment counts once, no matter which site it happened at.
| No-shows | Active appointments | Rate | |
|---|---|---|---|
| Centro | 17 | 169 | 10.1% |
| Angelópolis | 12 | 123 | 9.8% |
| Cholula | 14 | 82 | 17.1% |
| Clinic | 43 | 374 | 11.5% |
The last row isn't the average of the rows above it: it's the sum of the count columns, divided at the end.
The same rule works for any average. The clinic's average wait is the total minutes every patient seen spent waiting, divided by the number of patients seen (6,519 minutes over 331 patients: 19.7 minutes), not the average of each site's wait. That's why the clinic's data has espera_total_min (total wait in minutes) and not a column of averages: from totals you can always get to the right average, and from averages you can't.
Where it hides at work
This mistake rarely looks like a mistake. It looks like a spreadsheet with a column of percentages and, at the bottom, a cell labeled Average. Or a pivot table where you ask for the average of a column that was already a rate. Or an AI that hands you "the clinic's rate" without telling you how it got there.
Whenever you see a percentage for a total, ask: what got added up on top, and what got added up on the bottom? If the answer is "someone averaged percentages," be suspicious. If you have a spreadsheet with a column of percentages and an average at the bottom, go over it with your Maestro.
There's one case where the simple average is the answer: when the question is about the groups, not the appointments. "How is the typical site doing?" is a different question from "what share of appointments did we lose?" If you ever need it, give it its own name on the definition sheet, so nobody mistakes it for the clinic's rate.
Try it
In the editor, someone calculated the clinic's rate for the latest week by averaging the nine rates, one per site and specialty. Run the code to see what it prints, then fix the tasa_clinica line so it follows the rule.
The code calculates the clinic's no-show rate for the week of September 21 as the average of the nine rates (one per site and specialty), and gets 13.7%. Change only the tasaclinica line so it adds up the no-shows, adds up the active appointments and divides at the end. You're do
The code calculates the clinic's no-show rate for the week of September 21 as the average of the nine rates (one per site and specialty), and gets 13.7%. Change only the tasa_clinica line so it adds up the no-shows, adds up the active appointments and divides at the end. You're done when it prints 11.5%, the rate on Lucía's definition sheet.
Run your code to see what it prints and the value of its last expression. Every run starts fresh. Ctrl+Enter runs it. Tab indents; to leave the editor, press Escape, then Tab.
Ready to run your code.
Run your code to see its output here.
Data: citas-clinica, 117 rows
Enter saves a cell and Escape leaves it as it was. Leave a cell empty for a missing value.
| Row | Remove | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | |||||||||||
| 2 | |||||||||||
| 3 | |||||||||||
| 4 | |||||||||||
| 5 | |||||||||||
| 6 | |||||||||||
| 7 | |||||||||||
| 8 | |||||||||||
| 9 | |||||||||||
| 10 | |||||||||||
| 11 | |||||||||||
| 12 | |||||||||||
| 13 | |||||||||||
| 14 | |||||||||||
| 15 | |||||||||||
| 16 | |||||||||||
| 17 | |||||||||||
| 18 | |||||||||||
| 19 | |||||||||||
| 20 |
If you got 11.5%, compare it with what was there before: the average of the nine rows said 13.7%, more than two points higher. In Cholula's Nutrition row, with 12 active appointments, 3 no-shows make 25%, and that 25% counted in the average as much as Centro's General Medicine row with 97 appointments.