← Methods repository
concept

Pediatric Growth and Development Endpoints in RWE

The operational specification of pediatric growth (anthropometric z-scores/percentiles against an age- and sex-specific reference) and neurodevelopmental endpoints in real-world data, including reference-curve choice, age handling (chronological vs corrected), and the continuous-vs-threshold and cross-sectional-vs-conditional-growth estimand decisions.

Outcome_Measureoutcome_measurepediatricanthropometrygrowth-z-scoreneurodevelopmentlms-methodspecial-populations-methodsconditional-growth
Methods reference only. Use primary source citations and local policy before applying this in a study protocol, regulatory submission, payer dossier, or clinical decision.

In plain language

Growth looks very different in a 3-month-old versus a 3-year-old, so researchers never compare raw centimeters or kilograms across ages — instead, they convert each measurement into a z-score or percentile that says how a child ranks compared to healthy children of the exact same age and sex. This standardized number is the actual endpoint in pediatric studies, and it lets you ask whether a drug or disease bent a child's growth curve up or down relative to the reference population. One honest caveat: if you only have insurance claims data and no clinic-measured heights and weights, you cannot compute a z-score at all — only electronic health records or linked registry data contain the raw measurements you need.

Pediatric growth and development endpoints

are not raw measurements; they are derived outcomes whose meaning depends entirely on an externally specified reference. A 9 kg weight is uninterpretable until it is converted, conditional on exact age and sex, to a z-score (SD score) or percentile against a growth standard. The standard transformation is the LMS method (Cole & Green 1992): for the L (Box-Cox power), M (median), and S (coefficient of variation) at the child's age/sex, z = ((measure/M)^L - 1) / (LS) when L != 0, and z = ln(measure/M)/S when L = 0. From this you obtain weight-for-age (WAZ), length/height-for-age (HAZ/LAZ), weight-for-length (WHZ), and BMI-for-age (BAZ). Developmental endpoints are a separate* family: pass/fail on a validated screen (ASQ, M-CHAT, PEDS, Bayley), age at milestone acquisition, or a standardized scale score. Treating "pediatric outcomes" as one undifferentiated bucket is the first and most common error.

Core conceptual distinction

Three orthogonal choices define the endpoint and must each be pre-specified in the estimand. (1) Which reference, by age and prematurity: WHO Child Growth Standards (the prescriptive 0-5y standard from breastfed reference populations; WHO MGRS 2006) vs CDC 2000 growth charts (a descriptive US reference, conventionally used >=2y; Ogden 2002) vs Fenton/INTERGROWTH-21st preterm curves for the neonatal/early-infancy window vs condition-specific curves (Down syndrome, achondroplasia, cerebral palsy) where the general reference is clinically wrong. Mixing references across the age range produces artifactual discontinuities in z at the splice age. (2) Chronological vs corrected age: for infants born preterm, z-scores must use gestationally corrected age (chronological age minus weeks of prematurity) through ~24 months, or growth failure is systematically overstated. (3) Continuous z vs threshold vs conditional growth: the estimand can be a continuous z-score, a binary threshold (stunting HAZ < -2, wasting WHZ < -2, overweight BAZ >= 85th, obesity >= 95th percentile), the age at acquisition of a state, or a conditional/change-in-z quantity (growth velocity, SITAR/mixed-model trajectory) that asks whether a child tracked along their own centile. Single cross-sectional z answers "how big now"; conditional growth answers "did this exposure bend the trajectory" — they are different causal questions and usually need different models (a single GLM vs a mixed/MMRM longitudinal model; see mixed-effects-models-longitudinal-rwe).

Pros, cons, and trade-offs

- Continuous z-score vs binary threshold (stunting/wasting/obesity): Continuous z retains power, avoids arbitrary cutpoints, and is the default for comparative analyses; a threshold maps to a clinical label and a guideline action but discards information and is unstable near the cut. Prefer continuous z for the primary effect estimate and report the dichotomized version as a clinically interpretable secondary. - Single cross-sectional z vs conditional/repeated-measures growth: A one-timepoint z is cheap and easy but cannot separate "small baseline" from "stopped growing." A conditional-growth or mixed-model approach (change in z, velocity, SITAR) directly targets the trajectory effect and handles the within-child correlation, at the cost of needing >=2-3 well-timed measurements and more modeling judgment. Prefer conditional growth when the exposure plausibly acts over time (e.g., chronic therapy, nutrition). - Growth proxy codes vs measured anthropometry: ICD-10 codes (R62.50/.51 failure to thrive, R63.x, E66.x obesity, Z68.5x BMI-percentile category) are cheap and present in pure claims but capture only the clinician-flagged tail and miss the continuous distribution; measured height/weight from EHR vitals gives the true z but requires EHR or linkage. Prefer measured anthropometry; use codes only as a fallback outcome with explicit under-capture caveats and a validation substudy (claims-outcome-algorithm-ppv-sensitivity-rwe). - Standardized developmental scale vs milestone/screen code: A Bayley/ASQ score is a graded, validated endpoint but is rarely in claims and irregularly in EHR; a developmental-delay diagnosis (F88/F89, F80-F82) or early-intervention referral is administratively available but lags acquisition and reflects access to screening, not the underlying milestone. Prefer the scale when available; treat the code as an access-confounded proxy.

When to use

Any pediatric comparative-effectiveness, safety, nutritional, or HEOR study where growth or development is the outcome of interest (e.g., inhaled-corticosteroid effect on attained height, growth-hormone effectiveness, nutritional intervention, neurodevelopment after perinatal exposure); regulatory pediatric study plans and post-marketing requirements where growth/development is a mandated long-term endpoint; registry programs (disease-registry, product-registry) designed to capture serial anthropometry. Use measured anthropometry from EHR or linked data, the age- and prematurity-appropriate reference, exact age in days, and a longitudinal model when the question is about trajectory.

When NOT to use — and when it is actively misleading or dangerous

- Pure claims with no measured height/weight and no BMI-percentile Z-codes. You cannot derive a z-score from claims alone. Reporting "no growth effect" from a cohort where the outcome was never measured is a null produced by missingness, not biology. - Mixing references or ignoring corrected age. Splicing WHO and CDC at 2 years without harmonizing, or using chronological age for ex-preterm infants, manufactures z discontinuities and inflates apparent growth failure in the exposed arm if prematurity is unbalanced. - General reference for a condition that has its own curve. A child with Down syndrome plotted on WHO/CDC will look "stunted" by construction; using the general standard as the endpoint confounds the genetic condition with the exposure effect. - Dichotomizing a continuous z at a guideline cut as the primary endpoint when power is limited — you discard most of the signal and make the result hostage to a few children straddling -2 SD. - Conditional growth from irregular, exposure-driven measurement. If sicker (exposed) children are weighed more often, the measurement schedule is informative; a naive change-in-z is biased. Model the visit process or use a design (e.g., scheduled well-child visits) that decouples measurement from outcome.

Data-source operational depth

- Claims (FFS or commercial): No anthropometric values. The only growth signal is proxy coding — R62.50/.51 (failure to thrive / lack of expected normal physiological development), R63.4 (abnormal weight loss), R63.3 (feeding difficulties), E66.x (obesity), and the BMI-percentile-for-age Z-codes Z68.51-Z68.54 captured at well-child visits — plus developmental codes (F80-F82, F88, F89) and early-intervention/therapy procedure codes. Failure modes: these capture only the clinician-flagged tail (low sensitivity for the continuous distribution), Z68.5x is recorded inconsistently by payer/EHR-template, and Medicare Advantage is irrelevant in peds — the analog is Medicaid managed care, where encounter completeness varies by state and carve-outs (behavioral/developmental services are often carved out, dropping milestone data). Workaround: treat claims growth/development outcomes as algorithms requiring PPV/sensitivity validation, not gold standards. - EHR: The native home of growth endpoints — height/weight/head-circumference live in structured vitals, BMI percentile is often pre-computed (verify the reference and age basis the EHR used; do not trust an inherited percentile blindly). Failure modes: unit and decimal errors (lb vs kg, cm vs in) produce extreme z outliers — apply WHO/CDC biologically-implausible-value flags (e.g., |WAZ|>5, |HAZ|>5) before analysis; visit-driven capture means measurement timing is irregular and tied to illness; gestational age (for correction) is frequently missing in non-neonatal EHRs; developmental screens (ASQ/M-CHAT) live in flowsheets or notes, not always discrete fields, so NLP or flowsheet mapping is often required. - Registry: Disease and product registries (disease-registry, product-registry, pregnancy-registry) can mandate serial, protocolized anthropometry and standardized developmental assessment — the strongest source for growth trajectories — but suffer enrollment selection, differential loss to follow-up by severity, and incomplete capture of care delivered outside the registry network. - Linked claims-EHR(-birth/vital records): The ideal substrate: claims for cohort entry, exposure (pharmacy NDC + days_supply), continuous enrollment, and censoring; EHR vitals for the measured z-score outcome; birth/vital records for gestational age to enable corrected age. Linkage introduces selection (only the linkable subset), and birth-record gestational age must be reconciled with EHR-recorded GA before correction.

Worked linked claims+EHR example

Question: does initiation of medium/high-dose inhaled corticosteroids (ICS) vs leukotriene-receptor antagonists (LTRA) slow attained linear growth (HAZ) over 12 months in children aged 4-11 with persistent asthma, in a Medicaid + commercial claims database linked to EHR vitals. (1) Eligibility: age 4-11 at index, >=2 asthma diagnoses (ICD-10 J45.x), and 365 days of continuous medical + pharmacy enrollment before the first qualifying fill (so the new-user washout is observed, not missing). (2) Exposure / time zero: first fill of ICS or LTRA (NDC + fill_date + days_supply); arm assigned from that NDC; new-user restriction = no fill of either class in the 365-day lookback. (3) Outcome derivation: pull all EHR height measurements; compute exact age in days at each height as (measure_date - birth_date); convert to HAZ via the CDC 2000 LMS coefficients for sex and age in months (children are >=2y, so CDC is the conventional reference); apply implausible-value exclusion |HAZ|>5. (4) Endpoint = change in HAZ from the measurement closest to index_date (within +/-90 days) to the measurement closest to 12 months post-index (within +/-90 days) — a conditional growth endpoint, not a single cross-section. (5) Confounding: baseline covariates measured only in the [index_date-365, index_date] window — asthma severity proxies (rescue-inhaler fills, oral-steroid bursts, ED/hospital asthma claims), baseline HAZ, age, sex, season of index — feeding a propensity model balancing the two arms. (6) Analysis: a linear mixed model of HAZ over time with random child intercept/slope (mixed-effects-models-longitudinal-rwe) handles the within-child correlation and the irregular, +/-90-day measurement timing better than a crude two-point difference; censor at disenrollment, loss of EHR contact, and end of data. (7) Sensitivity: corrected vs chronological age has no effect here (all >=2y, term assumed) but would matter in an infant cohort; vary the measurement windows, the implausible-value flags, and add a negative-control outcome (negative-control-outcomes-rwe) to detect residual confounding by asthma severity. A naive single end-of-year HAZ (ignoring baseline height) would confound pre-existing short stature with an ICS effect — exactly the trap the conditional design avoids.

Regulatory note: pediatric study plans (FDA PSP/PREA, EMA PIP) frequently mandate growth and neurodevelopment as long-term safety endpoints; pre-specifying the reference, corrected-age rule, and continuous-vs-threshold estimand in protocol language is a regulatory expectation, not a nicety.

Interpreting the output

. The four-child example produces a z-score profile at a single time point. Child C-101 (female, 4 years, height 98.5 cm) has HAZ = −1.2, placing her at the 12th percentile on the WHO reference — below average but not in the range that defines stunting. Child C-103 (female, 8 years, height 116.2 cm) has HAZ = −2.1, at the 2nd percentile, meeting the WHO threshold for stunting (HAZ < −2). Children C-102 and C-104 are near or above the reference median.

Formal interpretation: HAZ = −1.2 means Child C-101's height is 1.2 standard deviations below the mean height of healthy girls of the same age in the WHO Multicentre Growth Reference Study population. This z-score is a position statement — it describes where the child sits relative to a normative reference derived from breastfed children in healthy environments, not relative to other children in the study cohort or the study's target disease population. A treatment effect on growth is estimated as the mean within-child change in HAZ from baseline to follow-up, not as a cross-sectional comparison of z-scores to the reference at one point in time.

Practical interpretation: the reference population is a deliberate, transparent assumption. Children with a treated chronic condition (e.g., severe asthma) may systematically differ from the WHO reference even at baseline, so reporting baseline HAZ alongside the change estimate is essential. A shift in HAZ from −1.5 to −1.2 (improvement) is clinically interpretable; crossing the −2.0 threshold toward or away from stunting is a regulatory milestone. Always report the reference used and justify it for the study population.

Worked example

Scenario

A researcher wants to compare the heights of four children enrolled in a clinical registry study. The children range from age 4 to age 9, so raw height in centimeters cannot be compared directly — a shorter number does not mean worse growth when the children are different ages. The researcher converts each raw height to a height-for-age z-score (HAZ) using CDC 2000 reference values, which gives every child a single comparable number. A z-score at or above -2.0 is considered normal; below -2.0 is classified as stunting.

Dataset

Four children in a registry, each with a single clinic-measured height. HAZ is derived from the CDC 2000 reference for the child's sex and age.

child_idsexage_yearsheight_cmhazpercentile_approx
C-101F498.5-1.212th
C-102M6118.00.362nd
C-103F8116.2-2.12nd
C-104M9137.50.879th

Steps

  • Raw heights alone are misleading: C-103 at 116.2 cm is taller than C-101 at 98.5 cm, yet C-103 has a lower z-score because a girl aged 8 is expected to be much taller than a girl aged 4.

  • For each child, look up the CDC 2000 reference median (M) and spread (L, S) for their exact age in months and sex — this is the LMS method.

  • Apply the LMS formula: z = ((height / M) raised to the power L, minus 1) divided by (L times S). A positive result means taller than average; negative means shorter than average.

  • C-101 (girl, age 4, 98.5 cm) yields HAZ = -1.2, placing her at roughly the 12th percentile — below average but within the normal range (above -2.0).

  • C-103 (girl, age 8, 116.2 cm) yields HAZ = -2.1, placing her just below the 2nd percentile — this crosses the stunting threshold of -2.0 SD.

  • C-102 (boy, age 6, 118.0 cm) and C-104 (boy, age 9, 137.5 cm) both have positive z-scores, meaning they are taller than average for their age and sex.

  • Because all four children now share the same z-score scale, the researcher can compare growth status across ages in a single analysis — something raw centimeters cannot support.

Result

HAZ values: C-101 = -1.2 (12th percentile, normal); C-102 = 0.3 (62nd percentile, normal); C-103 = -2.1 (2nd percentile, stunting — below the -2.0 SD threshold); C-104 = 0.8 (79th percentile, normal). Three of the four children fall within the normal range; one child (C-103) meets the HAZ < -2.0 definition of stunting, which would not have been identifiable by comparing raw heights across different ages.

Runnable example

python implementation

Derive height-for-age z-scores (HAZ) from EHR vitals using the LMS method, then build a per-child conditional growth endpoint (change in HAZ over a follow-up window). Required inputs (cleaned, de-duplicated): vitals : person_id, measure_date (datetime),...

import numpy as np
import pandas as pd

Z_IMPLAUSIBLE = 5.0       # WHO/CDC-style biologically implausible-value bound for height-for-age z
WINDOW_DAYS = 90          # tolerance for matching a measurement to a target timepoint
FOLLOWUP_DAYS = 365

def lms_zscore(value, L, M, S):
    # Cole-Green LMS transform; the L==0 branch is the log-normal limit.
    L = np.asarray(L, dtype=float)
    z = np.where(np.abs(L) < 1e-7,
                 np.log(value / M) / S,
                 ((value / M) ** L - 1.0) / (L * S))
    return z

def haz_from_vitals(vitals: pd.DataFrame, ref: pd.DataFrame) -> pd.DataFrame:
    v = vitals.copy()
    v["age_days"] = (v["measure_date"] - v["birth_date"]).dt.days
    v["age_months"] = (v["age_days"] / 30.4375).round().astype(int)   # exact-age basis, then key to ref grid
    v = v.merge(ref, on=["sex", "age_months"], how="inner")
    v["haz"] = lms_zscore(v["height_cm"].to_numpy(), v["L"], v["M"], v["S"])
    v = v[v["haz"].abs() <= Z_IMPLAUSIBLE]                             # drop unit/decimal-error outliers
    return v[["person_id", "measure_date", "age_days", "haz"]]

def conditional_growth(haz: pd.DataFrame, cohort: pd.DataFrame) -> pd.DataFrame:
    h = haz.merge(cohort[["person_id", "index_date", "arm"]], on="person_id")
    h["d_index"] = (h["measure_date"] - h["index_date"]).dt.days

    def nearest(grp, target):
        cand = grp[(grp["d_index"] - target).abs() <= WINDOW_DAYS]
        if cand.empty:
            return np.nan
        return cand.loc[(cand["d_index"] - target).abs().idxmin(), "haz"]

    rows = []
    for pid, grp in h.groupby("person_id"):
        haz_0 = nearest(grp, 0)
        haz_12 = nearest(grp, FOLLOWUP_DAYS)
        rows.append({"person_id": pid, "arm": grp["arm"].iloc[0],
                     "haz_baseline": haz_0, "haz_12m": haz_12,
                     "delta_haz": haz_12 - haz_0})
    out = pd.DataFrame(rows)
    return out.dropna(subset=["delta_haz"])   # require both anchored measurements
r implementation

HAZ derivation via the LMS method and a linear mixed model of HAZ over time (random child intercept + slope), which respects the within-child correlation and the irregular measurement timing better than a two-point difference. Inputs mirror the Python...

library(data.table)
library(lme4)

Z_IMPLAUSIBLE <- 5.0

haz_from_vitals <- function(vitals, ref) {
  setDT(vitals); setDT(ref)
  vitals[, age_days := as.integer(measure_date - birth_date)]
  vitals[, age_months := as.integer(round(age_days / 30.4375))]
  v <- merge(vitals, ref, by = c("sex", "age_months"))
  # Cole-Green LMS; L == 0 is the log-normal limit.
  v[, haz := fifelse(abs(L) < 1e-7,
                     log(height_cm / M) / S,
                     ((height_cm / M)^L - 1) / (L * S))]
  v[abs(haz) <= Z_IMPLAUSIBLE,
    .(person_id, measure_date, age_days, haz)]
}

fit_growth_model <- function(haz, cohort) {
  setDT(haz); setDT(cohort)
  d <- merge(haz, cohort[, .(person_id, index_date, arm)], by = "person_id")
  d[, years_since_index := as.numeric(measure_date - index_date) / 365.25]
  # arm x time interaction = differential change in HAZ trajectory; random slope per child.
  lmer(haz ~ arm * years_since_index + (years_since_index | person_id), data = d)
}