Study census, exposure and data coverage for a safety overview
Source:R/SafetyCensus.R
SafetyCensus.RdThe denominators a safety reader needs before any event count means anything: how many participants there are, how many are on treatment, how much person-time has accrued, who has left the study and why, and — the one most often missing — how completely the safety data itself has been collected.
Usage
SafetyCensus(
dfSubjects,
dfLabs = NULL,
dfECG = NULL,
dfAE = NULL,
dfDisposition = NULL,
strIDCol = "subjid",
strArmCol = "arm",
strTimeOnStudyCol = "timeonstudy",
strTimeOnTreatmentCol = "timeontreatment",
strLabVisitCol = "visnam",
strLabVisitNumCol = "visnum",
strECGVisitCol = "visnam",
strECGVisitNumCol = "visnum",
strCompleteCol = "compyn",
strReasonCol = "compreas",
chrDeathValues = c("DEATH", "DIED")
)Arguments
- dfSubjects
data.frameSubject-level domain, one row per participant.- dfLabs
data.frameorNULLLong-format lab results, for lab coverage by visit.- dfECG
data.frameorNULLLong-format ECG records, for ECG coverage by visit.- dfAE
data.frameorNULLAdverse events, for the AE reporting rate.- dfDisposition
data.frameorNULLStudy-completion domain, for disposition and deaths.- strIDCol
characterParticipant ID column, shared by every domain. Default:"subjid".- strArmCol
characterTreatment arm column indfSubjects; used only to count randomised participants, never to split a figure. Default:"arm".- strTimeOnStudyCol, strTimeOnTreatmentCol
characterPerson-time columns indfSubjects, in days. Defaults:"timeonstudy","timeontreatment".- strLabVisitCol, strLabVisitNumCol
characterVisit label and visit number columns indfLabs. Defaults:"visnam","visnum".- strECGVisitCol, strECGVisitNumCol
characterVisit label and visit number columns indfECG. Defaults:"visnam","visnum".- strCompleteCol, strReasonCol
characterCompletion flag and reason columns indfDisposition. Defaults:"compyn","compreas".- chrDeathValues
characterValues of the disposition reason column read as death. Default:c("DEATH", "DIED").
Value
list with three data.frames:
Census— one row per named figure (Label,Value,Denominator,Group), the study's denominators and exposure;Coverage— one row per domain per visit (Domain,Visit,VisitNum,Participants,Expected), data availability;Disposition— one row per disposition state (State,Participants).
Details
Coverage is not decoration. A low event rate at a visit where 40% of
participants have no lab result is not reassurance, and the only way to tell
those two situations apart is to publish the denominator beside the count.
Coverage therefore reports, per visit, how many participants have at least
one result against how many are expected.
Every figure is pooled across treatment arms. A study-team safety view is a blinded view, and FDA guidance treats even coded arms (A/B/C) as unblinded data, so no arm split is produced here.
Examples
dfSubjects <- data.frame(
subjid = c("S1", "S2", "S3"),
arm = c("A", "A", NA),
timeonstudy = c(120, 90, 30),
timeontreatment = c(110, 80, 0)
)
SafetyCensus(dfSubjects)$Census
#> Label Value Denominator Group
#> 1 Enrolled participants 3.0 NA Census
#> 2 Randomised to an arm 2.0 3 Census
#> 3 Received study drug 2.0 3 Census
#> 4 Deaths NA 3 Census
#> 5 Person-years on study 0.7 NA Exposure
#> 6 Person-years on treatment 0.5 NA Exposure
#> 7 Median days on treatment 95.0 NA Exposure
#> 8 Participants with a lab result NA 3 Follow-up
#> 9 Participants with an ECG NA 3 Follow-up
#> 10 Participants with a reported AE NA 3 Follow-up
#> 11 Participants with a disposition record NA 3 Follow-up