OncoGFR 1200 — Chemotherapy Dosing by eGFR Equation

Overview

A sub-analysis of the dose project using the OncoGFR 1200 cohort, which uniquely includes a measured GFR (mGFR, ⁵¹Cr-EDTA plasma clearance) as the gold standard.

The analysis asks: if chemotherapy were dosed from each estimated-GFR (eGFR) equation instead of measured GFR, how often would patients be over- or under-dosed? Every comparison is run on both the indexed (mL/min/1.73 m²) and non-indexed (absolute mL/min) GFR scale, with measured GFR as the reference throughout.

Two views of that question:

  • Dosing Heatmaps — the full exploratory grid: every equation × drug × subgroup, as heatmaps, plus LOESS sets against several kidney-function contrasts.

  • Grant figures — a focused cut for the grant: carboplatin only, plotted against the eGFRcr-cys / Cockcroft-Gault discordance index, with the cohort distribution and an overdose-threshold breakdown by frailty and cachexia. This page now lives on the separate Grant site, alongside the Sherley carboplatin figures that use the same index.

  • Dosing Heatmaps →

  • Grant figures → — carboplatin overdose risk vs the eGFRcr-cys / Cockcroft-Gault discordance index. Moved to the separate Grant site on 2026-09-29; the codebook below still documents it.

eGFR equations compared (reference = measured GFR)

Cockcroft-Gault · CKD-EPI Cr (2021) · CKD-EPI Cys · CKD-EPI Cr-Cys (2021) · EKFC Cr · EKFC Cys · EKFC Cr-Cys · CKD-EPI 4-marker

Drugs

Carboplatin (Calvert AUC 5) · Cisplatin · Methotrexate · Melphalan

Carboplatin overdose is defined against a tolerance band: ±15 % and ±20 % on the Dosing Heatmaps page, and ≥10 %, ≥15 % and ≥20 % on the Grant page.

Appendix — Variable codebook, logic and concepts

Reference for the Grant figures — now hosted on the separate Grant site — every input column, derived variable, function and figure constant they use, why each exists, and what the underlying ideas mean. Figure numbers below refer to that page. Rows marked NEW were added in the most recent update (10 % axis ticks, the −10 % reference line, the overlay figure, and the threshold / frailty figure).

A. Source files and input columns

Three Excel files, all gitignored — patient-level data never leaves the machine.

Source file Key Columns this page reads N
OncoGFR1200_MGH_chemo_CJASN.xlsx protocol the 8 equation columns × 2 scales, mGFRindex, mGFRnon_index 1,200
Frailty data to MGH.xlsx protocal (sic — misspelled in the source) fried_classification 592
Nutrition data.xlsx Protocol Number Cachexia, ASG-PPP 689

Kidney-function columns

Every equation is stored twice. Which one you use is not cosmetic — see concept C2.

eGFR family Equation Indexed (mL/min/1.73 m²) Absolute (mL/min)
reference Measured GFR (⁵¹Cr-EDTA) mGFRindex mGFRnon_index
eGFRcr CKD-EPI 2021 CKDEPIcr21index CKDEPIcr21non_index
eGFRcr EKFC 2021 EKFCcrindex EKFCcrnon_index
eGFRcys CKD-EPI 2012 CKDEPIcysindex CKDEPIcysnon_index
eGFRcys EKFC 2023 EKFCcysindex EKFCcysnon_index
eGFRcr-cys CKD-EPI 2021 CKDEPIcrcys21index CKDEPIcrcys21non_index
eGFRcr-cys EKFC 2023 EKFCcrcysindex EKFCcrcysnon-index (hyphen intentional)
ClCr Cockcroft-Gault CGindex CGnon_index
Panel CKD-EPI 4-marker CKDEPI4mark CKDEPI4marknon_index

B. Derived variables

B1 — The analysis variables

Variable Type Definition Why it exists
egfr_pctdiff_cg numeric, % (CKDEPIcrcys21non_index − CGnon_index) / CGnon_index × 100 The x-axis of every figure — the Jiaxuan discordance index (C4). Both terms absolute mL/min, as specified.
reg table, 8 rows equation id → family, display label, indexed column, absolute column One registry so a figure loops over equations instead of hard-coding 8 column names.
MGFR named vector index → mGFRindex, nonindex → mGFRnon_index Picks the reference column that matches the scale being analysed. Guards against comparing an indexed eGFR to an absolute mGFR.
cls Overdose / Underdose / Concordant carbo_class() output per patient × equation The outcome. Everything plotted is the share of patients with cls == "Overdose".
carbo_nonindex, carbo_index long tables, 9,600 rows 1,200 patients × 8 equations, carrying cls and egfr_pctdiff_cg Long format lets one plotting function serve all 8 panels.
fried_grp factor NEW fried_classification 0/1/2 → Non-frail / Pre-frail / Frail Figure 4. No codebook ships with the file, so the ordering was verified against external markers: age 67.4 → 69.4 → 70.9 (trend p = 6×10⁻⁵) and ECOG ≥2 at 0.0 % → 5.4 % → 27.4 % (p = 2×10⁻²⁷). Standard Fried ordering confirmed.
cachexia_grp factor NEW Cachexia 0/1 → No cachexia / Cachexia Figure 4.
asgppp_grp factor NEW ASG-PPP 1 → Malnourished, 2 → Well-nourished Figure 4. Direction established from the data, and it is the reverse of the intuitive “higher = worse”: 49.6 % of rating 1 are cachectic vs 11.3 % of rating 2 (Fisher p = 2×10⁻²⁸), with worse ECOG and lower BMI. See C10.
d_hist, n_tot, q data / 1,200 / quartiles non-missing rows of the index, its N, and its 25/50/75th centiles Figure 2 and its summary table.

B2 — Classification functions

Function Signature Logic
carbo_class() (gfr, mgfr, k_hi = 6, k_lo = 4) Overdose if 5(gfr+25) > k_hi·(mgfr+25); Underdose if < k_lo·(mgfr+25); else Concordant. Defaults are the ±20 % band (C3).
carbo_over_thr() (gfr, mgfr, thr) NEW Overdose-only indicator at an arbitrary tolerance: 5(gfr+25) > 5(1+thr)(mgfr+25). Generalises carbo_class so one call covers 10 %, 15 % and 20 %.
build_carbo_long() (scale) Expands the wide file to one row per patient × equation on the chosen scale, attaching cls and the index.
grant_loess() (cl, eq, direction) Fits the smooth, clips it to [0, 100] (C6), draws one panel.

B3 — Figure-control constants

Constant Value Purpose
PCTD_CG_XLIM c(-50, 40) Plot window for Figures 1 and 3. Holds 98.2 % of patients; keeps the smooth off sparse tails.
PCTD_CG_BREAKS seq(-60, 60, 10) NEW Ticks every 10 percentage points. Spans the full data range (−52 to +53) so the unclipped distribution is ticked end to end; clipped figures simply drop the breaks outside their window.
REF_LINE -10 NEW The single black dashed reference line, replacing the former grey zero line and solid median line.
pctd_x() layer list NEW Shared x-scale + visible black tick marks, so all four figures line up.
ref_vline() layer NEW The −10 % dashed rule, defined once.
BINW 5 Histogram bin width, percentage points.
CNT_MAX ceiling(max(count)/25)·25 NEW Tallest bin rounded up to a clean 25. Sets the right-hand axis of the overlay (C7).
THRESHOLDS c(0.10, 0.15, 0.20) NEW The three overdose tolerances in Figure 4.
CARBO_RED #F8766D The carboplatin hue from the original 5-drug panels, kept so the line is recognisable.

B4 — Figure 4 summary table

Field Meaning
domain NEW Which assessment the grouping comes from: Whole cohort / Fried frailty / Cachexia / ASG-PPP.
grp, grp_i NEW Group label, and its integer level. grp_i exists only to preserve clinical ordering — binding rows across domains collapses factors to character, which would sort “Frail, Non-frail, Pre-frail” alphabetically.
N, k NEW Patients in the cell, and how many were overdosed.
pct, lo, hi NEW k/N × 100 with an exact binomial 95 % CI (C8).

C. Concepts

C1 · Measured GFR is the gold standard. Every “overdose” on this page is defined against ⁵¹Cr-EDTA plasma clearance, not against another estimate. So the figures measure estimation error with a clinical consequence, not disagreement between two guesses.

C2 · Indexed vs absolute GFR. Indexed GFR (mL/min/1.73 m²) rescales everyone to a standard body size — right for staging CKD, because it makes patients comparable. Absolute GFR (mL/min) is the patient’s actual clearance — right for dosing, because a drug is cleared by the kidney the patient actually has. The relationship is absolute = indexed × BSA / 1.73 (verified in this dataset). Using an indexed GFR in Calvert systematically misdoses anyone whose body size is far from average, which is why the absolute scale is the primary analysis here.

C3 · Calvert and where the constants come from. Carboplatin is dosed to a target exposure: dose = AUC × (GFR + 25). At AUC 5 the dose is 5(GFR + 25). Overdosing by more than a fraction t means

\[5(\text{eGFR}+25) > (1+t)\cdot 5(\text{mGFR}+25)\]

so the right-hand constant is 5(1+t): 5.5 at 10 %, 5.75 at 15 %, 6 at 20 %. The mirror-image constants 5(1−t) give underdose. That is the whole of carbo_class() and carbo_over_thr() — the apparently magic 6 and 4 are just ±20 %.

C4 · The discordance index. (eGFRcr-cys − Cockcroft-Gault) / Cockcroft-Gault × 100. Cystatin C is not raised by muscle mass, so in a wasted patient creatinine stays deceptively low and Cockcroft-Gault reads high, while cystatin pulls the combined equation down. A negative index therefore flags “Cockcroft-Gault is flattering this kidney”. Because it is a ratio of two GFRs on the same scale, the BSA factor cancels — indexed and absolute versions agree to within 0.5 points here (rounding only).

C5 · Why the index is more discriminating for some equations. Cockcroft-Gault is the index’s own denominator, so the CG panel is partly self-referential and shows the steepest gradient (78.5 % → 1.2 %). The CKD-EPI Cr 2021 panel is a genuinely independent test and is much flatter (33 % → 15 %). Both are shown; only the second is independent evidence.

C6 · LOESS and the clipping. The outcome is binary per patient (overdosed or not). LOESS takes a locally weighted average of those 0/1 values in a sliding window (span = 0.9), which estimates the probability of overdose as a smooth function of the index. It is unconstrained, so where data are sparse it can return values above 100 % or below 0 % — the raw Cockcroft-Gault fit reached ~105 %. The drawn curve and band are therefore clipped to [0, 100]. The fit is not modified, so a curve lying flat on 0 % at the far right is at the edge of the data, not a genuine plateau.

C7 · The dual axis in Figure 3. Two quantities with different units share one panel. The overdose curve owns the left axis (0–100 %). The bars are drawn as count / CNT_MAX × 100 so they occupy the same 0–100 range, and the right axis inverts exactly that transform to relabel them as counts (or as % of cohort). Bar heights are identical in both variants — only the right-hand labelling changes. The right axis and the bars share a colour so the mapping needs no legend.

C8 · Exact binomial CIs. Figure 4’s smallest cell is 113 patients (Frail) with ~10 events. Normal-approximation intervals are unreliable that sparse and can run below zero, so the Clopper-Pearson exact interval is used instead. Overlapping intervals across groups are the reason the frailty and cachexia contrasts are reported as null.

C10 · Recovering an undocumented coding. Neither the frailty nor the nutrition file ships a codebook, so what 0/1/2 and 1/2 mean had to be recovered rather than assumed. The method is to predict what each candidate mapping implies for other variables and check which holds. Frailty should track age and performance status — it does, monotonically, so 0 = non-frail through 2 = frail. Nutrition rating should track cachexia — and there the answer inverts the intuitive reading: rating 1 is the malnourished group. This matters beyond labelling, because ASG-PPP is the only marker in Figure 4 with a visible separation, and knowing its direction turns an apparent confirmation of the grant hypothesis into a contradiction of it.

C9 · Why the −10 % line. A single fixed reference at −10 % replaces the old zero line and cohort-median line. Zero is not the clinically interesting point — it is where two estimates agree, which says nothing about dosing. −10 % sits where the overdose curve begins to climb steeply, so it reads as a candidate flag threshold rather than a statistical artefact.