library(metalite)
library(metalite.ae)
The purpose of this tutorial is to create production ready AE specification analyses by extending examples shown in the specific AE chapter of the R for Clinical Study Reports and Submission book.
The AE specification analysis is to provide tables to summarize details of different types of adverse events. With a metadata object created by metalite, there are three required functions to create AE specification analysis table using metalite.ae:
prepare_ae_specific()
: prepare analysis raw
datasets.format_ae_specific()
: prepare analysis (mock) outdata
with proper format.tlf_ae_specific()
: transfer (mock) output dataset to
RTF table.There are three optional functions to extend AE specification analysis.
extend_ae_specific_inference()
: add risk difference
inference results based on M&N method.extend_ae_specific_duration()
: add average duration of
AE.extend_ae_specific_events()
: add average number of AE
events.An example output:
In metalite.ae, we created an example dataset using ADSL and ADAE datasets from the metalite package.
<- meta_ae_example()
meta
meta#> ADaM Meta Data:
#> .$data_population Population data with 254 subjects
#> .$data_observation Observation data with 1191 records
#> .$plan Analysis plan with 16 plans
#>
#>
#> Analysis population type:
#> name id group var subset label
#> 1 'apat' 'USUBJID' 'TRTA' SAFFL == 'Y' 'All Participants as Treated'
#>
#>
#> Analysis observation type:
#> name id group var subset label
#> 1 'wk12' 'USUBJID' 'TRTA' SAFFL == 'Y' 'Weeks 0 to 12'
#> 2 'wk24' 'USUBJID' 'TRTA' AOCC01FL == 'Y' 'Weeks 0 to 24'
#>
#>
#> Analysis parameter type:
#> name label
#> 1 'rel' 'drug-related adverse events'
#> 2 'aeosi' 'adverse events of special interest'
#> 3 'any' 'any adverse events'
#> 4 'ser' 'serious adverse events'
#> subset
#> 1 AEREL %in% c('POSSIBLE', 'PROBABLE')
#> 2 AEOSI == 'Y'
#> 3
#> 4 AESER == 'Y'
#>
#>
#> Analysis function:
#> name label
#> 1 'ae_summary' 'Table: adverse event summary'
#> 2 'ae_listing' 'Listing: adverse event'
#> 3 'ae_specific' 'Table: specific adverse event'
The same metadata structure is used to support all analysis examples in metalite.ae. More details can be found on the metalite package website.
The prepare_ae_specific()
function is used to calculate
statistics required for AE specification analysis using pre-specified
keywords in meta
. The input of the function is a
meta
object created by metalite. The output of the function
is an outdata
object that contains a list of analysis raw
datasets.
<- prepare_ae_specific(
outdata
meta,population = "apat",
observation = "wk12",
parameter = "rel"
)
outdata#> List of 13
#> $ meta :List of 7
#> $ population : chr "apat"
#> $ observation : chr "wk12"
#> $ parameter : chr "rel"
#> $ n :'data.frame': 138 obs. of 4 variables:
#> $ order : num [1:138] 1 100 200 900 1000 ...
#> $ group : chr [1:4] "Placebo" "Low Dose" "High Dose" "Total"
#> $ reference_group: num 1
#> $ prop :'data.frame': 138 obs. of 4 variables:
#> $ diff :'data.frame': 138 obs. of 2 variables:
#> $ n_pop :'data.frame': 1 obs. of 4 variables:
#> $ name : chr [1:138] "Participants in population" "with one or more drug-related adverse events" "with no drug-related adverse events" "" ...
#> $ components : chr [1:2] "soc" "par"
The output dataset contains commonly used statistics. The variable is
indexed by the order of outdata$group
.
$group
outdata#> [1] "Placebo" "Low Dose" "High Dose" "Total"
The row is indexed by the order of outdata$name
.
head(data.frame(outdata$order, outdata$name))
#> outdata.order outdata.name
#> 1 1 Participants in population
#> 2 100 with one or more drug-related adverse events
#> 3 200 with no drug-related adverse events
#> 4 900
#> 5 1000 Cardiac disorders
#> 6 1021 Atrial fibrillation
n_pop
: participants in population.$n_pop
outdata#> n_1 n_2 n_3 n_4
#> 1 86 84 84 254
n
: number of subjects with AE.head(outdata$n)
#> n_1 n_2 n_3 n_4
#> 1 86 84 84 254
#> 2 44 73 70 187
#> 3 42 11 14 67
#> 4 NA NA NA NA
#> 122 6 7 4 17
#> 25 1 0 2 3
prop
: proportion of subjects with AE.head(outdata$prop)
#> prop_1 prop_2 prop_3 prop_4
#> 1 NA NA NA NA
#> 2 51.162791 86.904762 83.333333 73.622047
#> 3 48.837209 13.095238 16.666667 26.377953
#> 4 NA NA NA NA
#> 122 6.976744 8.333333 4.761905 6.692913
#> 25 1.162791 0.000000 2.380952 1.181102
diff
: risk difference compared with the
reference_group
.head(outdata$diff)
#> diff_2 diff_3
#> 1 NA NA
#> 2 35.741971 32.170543
#> 3 -35.741971 -32.170543
#> 4 NA NA
#> 122 1.356589 -2.214839
#> 25 -1.162791 1.218162
After we have the raw analysis results, we can use
format_ae_specific()
to prepare the outdata for production
ready RTF tables.
<- outdata |> format_ae_specific()
tbl head(tbl$tbl)
#> name n_1 prop_1 n_2 prop_2 n_3
#> 1 Participants in population 86 <NA> 84 <NA> 84
#> 2 with one or more drug-related adverse events 44 (51.2) 73 (86.9) 70
#> 3 with no drug-related adverse events 42 (48.8) 11 (13.1) 14
#> 4 NA <NA> NA <NA> NA
#> 122 Cardiac disorders 6 (7.0) 7 (8.3) 4
#> 25 Atrial fibrillation 1 (1.2) 0 (0.0) 2
#> prop_3 n_4 prop_4
#> 1 <NA> 254 <NA>
#> 2 (83.3) 187 (73.6)
#> 3 (16.7) 67 (26.4)
#> 4 <NA> NA <NA>
#> 122 (4.8) 17 (6.7)
#> 25 (2.4) 3 (1.2)
The display
argument allows us to select statistics. For
example, we can add risk difference.
<- outdata |> format_ae_specific(display = c("n", "prop", "diff"))
tbl head(tbl$tbl)
#> name n_1 prop_1 n_2 prop_2 n_3
#> 1 Participants in population 86 <NA> 84 <NA> 84
#> 2 with one or more drug-related adverse events 44 (51.2) 73 (86.9) 70
#> 3 with no drug-related adverse events 42 (48.8) 11 (13.1) 14
#> 4 NA <NA> NA <NA> NA
#> 122 Cardiac disorders 6 (7.0) 7 (8.3) 4
#> 25 Atrial fibrillation 1 (1.2) 0 (0.0) 2
#> prop_3 diff_2 diff_3
#> 1 <NA> NA NA
#> 2 (83.3) 35.7 32.2
#> 3 (16.7) -35.7 -32.2
#> 4 <NA> NA NA
#> 122 (4.8) 1.4 -2.2
#> 25 (2.4) -1.2 1.2
For advanced analysis, we need extend_*()
functions. For
example, we can use extend_ae_specific_inference()
to add
95% confidence interval based on Miettinen and Nurminen (M&N)
method. The details of the M&N method can be found in the rate
compare vignette
<- outdata |>
tbl extend_ae_specific_inference() |>
format_ae_specific(display = c("n", "prop", "diff", "diff_ci"))
head(tbl$tbl)
#> name n_1 prop_1 n_2 prop_2 n_3
#> 1 Participants in population 86 <NA> 84 <NA> 84
#> 2 with one or more drug-related adverse events 44 (51.2) 73 (86.9) 70
#> 3 with no drug-related adverse events 42 (48.8) 11 (13.1) 14
#> 4 NA <NA> NA <NA> NA
#> 122 Cardiac disorders 6 (7.0) 7 (8.3) 4
#> 25 Atrial fibrillation 1 (1.2) 0 (0.0) 2
#> prop_3 diff_2 ci_2 diff_3 ci_3
#> 1 <NA> NA (-4.4, 0.0) NA (-4.4, 0.0)
#> 2 (83.3) 35.7 (22.4, 48.0) 32.2 (18.4, 44.8)
#> 3 (16.7) -35.7 (-48.0, -22.4) -32.2 (-44.8, -18.4)
#> 4 <NA> NA <NA> NA <NA>
#> 122 (4.8) 1.4 (-7.3, 10.2) -2.2 (-10.3, 5.6)
#> 25 (2.4) -1.2 (-6.3, 3.3) 1.2 (-4.2, 7.3)
We can use extend_ae_specific_duration()
to add average
duration of AE.
<- outdata |>
tbl extend_ae_specific_duration(duration_var = "ADURN") |>
format_ae_specific(display = c("n", "prop", "dur"))
head(tbl$tbl)
#> name n_1 prop_1 dur_1 n_2
#> 1 Participants in population 86 <NA> NA 84
#> 2 with one or more drug-related adverse events 44 (51.2) 29.0 ( 3.5) 73
#> 3 with no drug-related adverse events 42 (48.8) NA 11
#> 4 NA <NA> NA NA
#> 122 Cardiac disorders 6 (7.0) 27.1 ( 5.9) 7
#> 25 Atrial fibrillation 1 (1.2) 1.3 ( 0.2) 0
#> prop_2 dur_2 n_3 prop_3 dur_3
#> 1 <NA> NA 84 <NA> NA
#> 2 (86.9) 27.2 ( 3.2) 70 (83.3) 30.6 ( 2.2)
#> 3 (13.1) NA 14 (16.7) NA
#> 4 <NA> NA NA <NA> NA
#> 122 (8.3) 16.1 ( 3.5) 4 (4.8) 1.5 ( 0.4)
#> 25 (0.0) 43.8 ( 9.8) 2 (2.4) 87.2 (22.5)
We can use extend_ae_specific_events()
to add average
number of AE per subject.
<- outdata |>
tbl extend_ae_specific_events() |>
format_ae_specific(display = c("n", "prop", "events"))
head(tbl$tbl)
#> name n_1 prop_1 events_1 n_2
#> 1 Participants in population 86 <NA> NA 84
#> 2 with one or more drug-related adverse events 44 (51.2) 0.7 ( 0.1) 73
#> 3 with no drug-related adverse events 42 (48.8) NA 11
#> 4 NA <NA> NA NA
#> 122 Cardiac disorders 6 (7.0) 2.3 ( 0.6) 7
#> 25 Atrial fibrillation 1 (1.2) 1.8 ( 0.6) 0
#> prop_2 events_2 n_3 prop_3 events_3
#> 1 <NA> NA 84 <NA> NA
#> 2 (86.9) 1.6 ( 0.2) 70 (83.3) 1.5 ( 0.2)
#> 3 (13.1) NA 14 (16.7) NA
#> 4 <NA> NA NA <NA> NA
#> 122 (8.3) 1.9 ( 0.4) 4 (4.8) 1.2 ( 0.2)
#> 25 (0.0) 1.7 ( 0.3) 2 (2.4) 1.7 ( 0.3)
The mock
argument allows us to create a mock table
easily.
Note: The purpose of the mock
argument is not to create
a comprehensive mock table template, but a handy way to help user create
a mock table that mimics the exact output layout.
Additional work is required to develop a flexible mock table generation tool (for example, a dedicated mock table generation package).
<- outdata |> format_ae_specific(mock = TRUE)
tbl head(tbl$tbl)
#> name n_1 prop_1 n_2 prop_2 n_3
#> 1 Participants in population xx <NA> xx <NA> xx
#> 2 with one or more drug-related adverse events xx (xx.x) xx (xx.x) xx
#> 3 with no drug-related adverse events xx (xx.x) xx (xx.x) xx
#> 4 <NA> <NA> <NA> <NA> <NA>
#> 5 Cardiac disorders x (x.x) x (x.x) x
#> 6 Atrial fibrillation x (x.x) x (x.x) x
#> prop_3 n_4 prop_4
#> 1 <NA> xxx <NA>
#> 2 (xx.x) xxx (xx.x)
#> 3 (xx.x) xx (xx.x)
#> 4 <NA> <NA> <NA>
#> 5 (x.x) xx (x.x)
#> 6 (x.x) x (x.x)
The last step is to prepare the RTF table using
tlf_ae_specific()
.
|>
outdata format_ae_specific() |>
tlf_ae_specific(
meddra_version = "24.0",
source = "Source: [CDISCpilot: adam-adsl; adae]",
path_outtable = "rtf/ae0specific1.rtf"
)#> The output is saved in/rtmp/RtmpPhK17m/Rbuild1a125d24fe88/metalite.ae/vignettes/rtf/ae0specific1.rtf
The tlf_ae_specific()
function also provides some
commonly used arguments to customize the table.
|>
outdata format_ae_specific() |>
tlf_ae_specific(
meddra_version = "24.0",
source = "Source: [CDISCpilot: adam-adsl; adae]",
col_rel_width = c(6, rep(1, 8)),
text_font_size = 8,
orientation = "landscape",
path_outtable = "rtf/ae0specific2.rtf"
)#> The output is saved in/rtmp/RtmpPhK17m/Rbuild1a125d24fe88/metalite.ae/vignettes/rtf/ae0specific2.rtf
The mock table can also be generated.
|>
outdata format_ae_specific(mock = TRUE) |>
tlf_ae_specific(
meddra_version = "24.0",
source = "Source: [CDISCpilot: adam-adsl; adae]",
path_outtable = "rtf/mock_ae0specific1.rtf"
)#> The output is saved in/rtmp/RtmpPhK17m/Rbuild1a125d24fe88/metalite.ae/vignettes/rtf/mock_ae0specific1.rtf