Computing WHO growth percentiles on-device
Every baby tracker shows growth percentiles. "Your daughter is in the 72nd percentile for weight." It looks like a lookup — find the row for her age, compare, print a number. It isn't. And the ways it goes wrong are interesting enough to be worth writing down. I ended up implementing this properly for a baby journal app, and published the result as who-growth-standards — MIT, zero dependencies,…
Every baby tracker displays growth percentiles, indicating where a child's growth stands relative to others of the same age and sex. However, the reality behind the simple lookup process is far more complex. The WHO Child Growth Standards only provide three numbers per age and sex – the L, M, and S values. While M represents the median (50th percentile) and S is the coefficient of variation, L is a Box-Cox power that manages skew in the distribution of growth data, which is not normally distributed.
To calculate percentiles, the z-score is determined using the formula: z = ((X / M)^L − 1) / (L × S), and then the normal cumulative distribution function is applied to that z-score. Despite the apparent simplicity of this formula, several problems arise when implementing it. One issue is the division by zero when L equals zero, which occurs in certain indicators.
To address this, the Box-Cox transform is modified to use the logarithmic form when L approaches zero. Another problem is catastrophic cancellation when L is extremely small, causing the (X/M)^L − 1 expression to lose significant digits. The solution is to handle this case explicitly and set the threshold for convergence at around 1e-6.
Additionally, the WHO tables are often provided as Excel files, which can lead to inaccuracies if hard-coded anchor points are used for interpolation. A better approach is to bundle all the data and generate the necessary code to access the tables. This ensures that the data used is accurate and up-to-date, reducing the chances of errors in percentile calculations.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.