The PFS censoring decision table you can paste into a SAP
Most PFS disagreements are not statistical. They are two people reading the same
protocol sentence and producing different CNSR values, three months apart, with
nothing written down in between.
The fix is unglamorous: one decision table, agreed before anyone writes code, that says exactly what each patient situation produces. It goes in the SAP, the same wording goes in the ADRG, and the derivation comments point back at it. What follows is that table, plus the ADaM details that reliably survive first review and then fail second review.
The table
Each row is a patient situation. Each row produces exactly one CNSR value and
one event date. If a situation is not on this list, it is a protocol question,
not a programming decision.
| # | Situation | CNSR | Event / censor date | EVNTDESC |
|---|---|---|---|---|
| 1 | Documented progression | 0 | Date of the assessment showing progression | PROGRESSION |
| 2 | Death, no prior progression | 0 | Date of death | DEATH |
| 3 | No baseline assessment | 1 | Randomisation date | NO BASELINE ASSESSMENT |
| 4 | Baseline only, no post-baseline assessment | 1 | Randomisation date | NO POST-BASELINE ASSESSMENT |
| 5 | Progression after two or more missed assessments | 1 | Last adequate assessment before the missed window | PROGRESSION AFTER MISSED VISITS |
| 6 | New anticancer therapy started, no prior progression | 1 | Last adequate assessment before therapy | NEW ANTICANCER THERAPY |
| 7 | Withdrew consent | 1 | Last adequate assessment | WITHDRAWAL |
| 8 | Lost to follow-up | 1 | Last adequate assessment | LOST TO FOLLOW-UP |
| 9 | Alive and progression-free at cut-off | 1 | Last adequate assessment | ONGOING |
Two definitions have to be pinned in the SAP or rows 5–9 are ambiguous:
- Adequate assessment. An assessment that could have detected progression — meaning the required lesions were actually imaged, not merely that a visit record exists. A visit with a missing scan is not an adequate assessment.
- The missed-visit window. “Two or more missed assessments” only means something once the protocol’s scheduled interval and its visit window are stated. Write the interval into the row.
Where teams disagree, and what to do about it
Row 6 is a sensitivity analysis, not a fact. Censoring at new anticancer therapy is one convention; treating it as an event is another; ignoring it is a third. Regulatory reviewers routinely ask for the alternative. Decide the primary in the SAP and pre-specify the sensitivity — retrofitting it later means re-opening the define.xml.
Row 5 has a quiet failure mode. If you censor at the last adequate assessment, and that assessment is months before an obvious progression, you have discarded a real event. That is the intended conservative behaviour, but it needs saying in the ADRG, because a reviewer comparing the listing to the KM curve will otherwise ask why.
Rows 3 and 4 are different rows on purpose. Collapsing them loses the
distinction between a patient who never had a baseline and one who had a
baseline and then vanished. Different EVNTDESC, same CNSR, and the listing
tells the story.
The ADaM details that fail second review
CNSR is inverted from what most people expect. In ADaM, CNSR = 0 is the
event and CNSR = 1 is the censor. Several SAS survival conventions use the
opposite. This single flip has produced more silently-wrong KM curves than any
other ADTTE mistake, and it is invisible in a summary table — the curve just
bends the wrong way. Assert it in QC rather than trusting it.
Time is a derived variable, and the +1 is a decision. AVAL is normally
AVAL = ADT - STARTDT + 1
in days, because the randomisation day counts as day 1. If your SAP says months,
state the divisor explicitly (30.4375 is common and is a choice, not a
constant). Put the unit in AVALU and do not leave it implied by the parameter
name.
STARTDT is not always randomisation. For a single-arm study it is often
first dose. Whatever it is, it comes from ADSL, not from re-deriving it in
ADTTE, or the two datasets will drift.
Traceability is three variables, not a comment. SRCDOM, SRCVAR and
SRCSEQ should point at the exact record in ADRS or RS that produced the
event date. A reviewer who cannot get from a KM point back to the source record
in two steps will ask you to do it for them, by email, in a month.
The QC that actually catches things
Comparing your output to a second programmer’s output finds disagreements but does not tell you who is right. These checks tell you something is wrong regardless of who wrote them:
- Every
CNSR = 0record has anEVNTDESCfrom rows 1–2, and everyCNSR = 1has one from rows 3–9. No blanks, no values outside the table. ADT >= STARTDTfor every record, with no exceptions and no silent drops.- Every subject in the analysis population appears exactly once per
PARAMCD. - The count of
CNSR = 0matches the number of events printed on the KM output. - Every
EVNTDESCvalue that appears in the data also appears in the table above — a value that appears in neither the SAP nor the table is a defect, even if it looks reasonable.
That last check is the one people skip, and it is the one that finds the category somebody invented at 11pm.
Provenance: this post makes no measured claims. The structure and variable definitions follow the CDISC ADaMIG time-to-event structure; the censoring rows follow conventions in common use for oncology PFS. It is a template to be adapted against your own protocol and SAP, not a substitute for either. No sponsor data, study, or compound is referenced — all examples are generic.