Adverse Events (AE)
Livia Pierotti
2026-04-01
Source:vignettes/adverse_events.Rmd
adverse_events.RmdIntroduction
This tutorial demonstrates how to generate adverse event (AE) summary
tables in R using the grstat package. AE tables are a
standard tool in clinical research for evaluating the severity (grade)
of events and identifying specific AE terms.
In this tutorial, it is demonstrated how to use two key functions:
ae_table_grade(), which creates table(s) summarising AE grades overall.ae_table_soc(), which summarises adverse events by System Organ Class (SOC) and by grades. It reports the number and proportion of patients experiencing at least one event within each SOC, based on their maximum recorded AE grade.
Additional features are available via the help()
function.
First, install packages if needed and load them.
Data Overview
The function grstat_example()returns a set of example
datasets used to demonstrate data usage.
This analysis focuses on two datasets:
-
ae, which contains data on adverse events. -
enrolres, which includes all patients and their respective treatment arms.
The AE table provides one row for each adverse event reported for a patient, capturing key details such as the event term, its grade, the associated System Organ Class, whether it is related to the study treatment, and whether it meets the criteria for a serious adverse event. A single patient may therefore appear multiple times if they experience several events, while those with no adverse events do not appear in the table at all.
tm = grstat_example(p_na=0.1)
attach(tm, warn.conflicts=FALSE)
head(ae, 4)## # A tibble: 4 × 7
## subjid aesoc aeterm aegr sae aerel crfname
## <int> <chr> <chr> <dbl> <fct> <chr> <chr>
## 1 1 Psychiatric disorders Subst… 1 No Stan… ae
## 2 1 Social circumstances Cultu… 1 No Expe… ae
## 3 1 Pregnancy, puerperium and perinatal c… Fetal… 2 Yes Canc… ae
## 4 1 Eye disorders NA 1 No Radi… ae
head(enrolres,4)## # A tibble: 4 × 5
## subjid arm arm3 date_inclusion crfname
## <int> <fct> <fct> <date> <chr>
## 1 1 Control Treatment B 2023-01-22 enrolres
## 2 2 Control Control 2023-03-12 enrolres
## 3 3 Treatment Treatment A 2023-03-30 enrolres
## 4 4 Control Control 2023-04-03 enrolres
Grade Tables only: ae_table_grade()
The function ae_table_grade() summarises toxicity data
at the patient level.
The measure argument controls how AE grades are
summarised:
-
measure = "max"summarises the worst reported AE grade observed for each patient. Rows are mutually exclusive. -
measure = "sup"summarises cumulative grade thresholds. For example,Grade ≥ 3counts patients with at least one AE of grade 3, 4, or 5. -
measure = "eq"summarises exact-grade occurrence. For example,Grade 3counts patients with at least one grade 3 AE.
Percentages are calculated using the total number of patients as denominator.
By default, all three summaries are returned in a single table. To
return only one summary, specify the corresponding measure
value.
Use as_flextable() to format the output as a
flextable and add footnotes or other formatting as
needed.
Use cases are described below. See help(ae_table_grade)
for the full list of arguments and some more examples.
Default: AE Table Grades - incuding All Variants (Max, Sup, Eq)
ae_table_grade(data_ae=ae, data_pat=enrolres) %>%
as_flextable() %>%
fontsize(size = 8, part = "all") %>%
padding(padding.top=0, padding.bottom=0)Measure |
Level |
All patients |
|---|---|---|
Patients by maximum AE grade |
Grade 1 |
41 (20%) |
Grade 2 |
64 (32%) |
|
Grade 3 |
50 (25%) |
|
Grade 4 |
31 (16%) |
|
Grade 5 |
3 (2%) |
|
Patients with at least one AE at or above each grade |
Grade ≥ 1 |
189 (94%) |
Grade ≥ 2 |
148 (74%) |
|
Grade ≥ 3 |
84 (42%) |
|
Grade ≥ 4 |
34 (17%) |
|
Grade = 5 |
3 (2%) |
|
Patients with at least one AE at each grade |
Grade 1 |
156 (78%) |
Grade 2 |
103 (52%) |
|
Grade 3 |
56 (28%) |
|
Grade 4 |
33 (16%) |
|
Grade 5 |
3 (2%) |
|
AE grade completeness |
No AE reported |
8 (4%) |
All grades missing |
3 (2%) |
|
Some grades missing |
59 (29%) |
Alternative: Maximum AE grade per patient per arm
As an extra example of AE grade table, a table of maximum grade per patient and per arm (i.e. variant = “max”) is also presented.
ae_table_grade(data_ae=ae, data_pat=enrolres, arm="arm", variant="max") %>%
as_flextable() %>%
add_footer_lines("Percentages reflect the proportion of patients whose maximum AE grade was as indicated per given arm.") %>%
fontsize(size = 8, part = "all") %>%
padding(padding.top=0, padding.bottom=0)Measure |
Level |
Treatment arm |
Total |
|
|---|---|---|---|---|
Control |
Treatment |
|||
Patients by maximum AE grade |
No AE reported |
3 (3%) |
5 (5%) |
8 (4%) |
Grade 1 |
24 (24%) |
17 (17%) |
41 (20%) |
|
Grade 2 |
34 (34%) |
30 (30%) |
64 (32%) |
|
Grade 3 |
25 (25%) |
25 (25%) |
50 (25%) |
|
Grade 4 |
11 (11%) |
20 (20%) |
31 (16%) |
|
Grade 5 |
2 (2%) |
1 (1%) |
3 (2%) |
|
All grades missing |
1 (1%) |
2 (2%) |
3 (2%) |
|
Percentages reflect the proportion of patients whose maximum AE grade was as indicated per given arm. | ||||
SOC’s tables: ae_table_soc()
The function ae_table_soc() summarises AE grades by
event group at the patient level.
The main grouping variable is defined by group1, which
is typically the System Organ Class (SOC). An optional second grouping
variable, group2, can be used for more detailed summaries,
for example by preferred term within SOC.
It uses the same measure argument as
ae_table_grade(), but only one is used. By default,
measure = "max", as this is the most common summary for
safety tables. For each group, patients are then classified according to
the maximum reported AE grade observed within that group.
The resulting table contains one row per group1 level
and one column per grade. The tot column reports the number
of patients with at least one AE in the corresponding group. The
na column reports patients with at least one AE in the
group but no available grade for the maximum-grade assessment.
The resulting data frame can be piped to as_flextable()
to produce a formatted table. In the header, N is the total
number of patients. Percentages are calculated using this total as
denominator.
Default: AE maximum grades by SOC
ae_table_soc(data_ae=ae, data_pat=enrolres, group1="aesoc") %>%
as_flextable() %>%
delete_rows(i=11:27) %>%
add_footer_lines("In the header, N represents the number of patients.") %>%
add_footer_lines("Percentages reflect the proportion of patients whose maximum AE grade was as indicated.") All patients (N=200) |
|||||||
|---|---|---|---|---|---|---|---|
AE SOC |
G1 |
G2 |
G3 |
G4 |
G5 |
NA |
Tot |
Social circumstances |
21 (10%) |
10 (5%) |
6 (3%) |
4 (2%) |
3 (2%) |
44 (22%) |
|
Eye disorders |
17 (8%) |
12 (6%) |
6 (3%) |
2 (1%) |
6 (3%) |
43 (22%) |
|
Congenital, familial and genetic disorders |
20 (10%) |
10 (5%) |
4 (2%) |
5 (2%) |
3 (2%) |
42 (21%) |
|
Pregnancy, puerperium and perinatal conditions |
11 (6%) |
9 (4%) |
2 (1%) |
2 (1%) |
7 (4%) |
31 (16%) |
|
Immune system disorders |
13 (6%) |
6 (3%) |
6 (3%) |
2 (1%) |
3 (2%) |
30 (15%) |
|
Injury, poisoning and procedural complications |
13 (6%) |
8 (4%) |
3 (2%) |
2 (1%) |
4 (2%) |
30 (15%) |
|
Neoplasms benign, malignant, and unspecified |
11 (6%) |
10 (5%) |
1 (0%) |
1 (0%) |
5 (2%) |
28 (14%) |
|
Hepatobiliary disorders |
14 (7%) |
7 (4%) |
1 (0%) |
1 (0%) |
3 (2%) |
26 (13%) |
|
Cardiac disorders |
7 (4%) |
3 (2%) |
7 (4%) |
4 (2%) |
2 (1%) |
23 (12%) |
|
Respiratory, thoracic and mediastinal disorders |
9 (4%) |
5 (2%) |
6 (3%) |
1 (0%) |
2 (1%) |
23 (12%) |
|
No Declared AE |
8 (4%) |
8 (4%) |
|||||
In the header, N represents the number of patients. | |||||||
Percentages reflect the proportion of patients whose maximum AE grade was as indicated. | |||||||
Alternative: AE maximum grades by SOC and term, stratified by arm
ae_table_soc(data_ae=ae, data_pat=enrolres, arm="arm", group1="aesoc", group2="aeterm") %>%
as_flextable() %>%
delete_rows(i=11:165) %>%
add_footer_lines("In the header, N represents the number of patients.") %>%
add_footer_lines("Percentages reflect the proportion of patients whose maximum AE grade was as indicated.")Control (N=100) |
Treatment (N=100) |
||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AE SOC |
AE Term (HLGT) |
G1 |
G2 |
G3 |
G4 |
G5 |
NA |
Tot |
G1 |
G2 |
G3 |
G4 |
G5 |
NA |
Tot |
Social circumstances |
Cultural issues |
5 (5%) |
2 (2%) |
2 (2%) |
1 (1%) |
10 (10%) |
3 (3%) |
1 (1%) |
2 (2%) |
1 (1%) |
7 (7%) |
||||
Economic conditions affecting care |
1 (1%) |
1 (1%) |
2 (2%) |
1 (1%) |
1 (1%) |
1 (1%) |
3 (3%) |
||||||||
Family support issues |
7 (7%) |
3 (3%) |
10 (10%) |
2 (2%) |
1 (1%) |
2 (2%) |
5 (5%) |
||||||||
Social and environmental issues |
2 (2%) |
1 (1%) |
1 (1%) |
4 (4%) |
2 (2%) |
1 (1%) |
1 (1%) |
1 (1%) |
1 (1%) |
6 (6%) |
|||||
2 (2%) |
2 (2%) |
2 (2%) |
2 (2%) |
||||||||||||
Eye disorders |
Corneal disorders |
3 (3%) |
1 (1%) |
2 (2%) |
6 (6%) |
1 (1%) |
1 (1%) |
1 (1%) |
3 (3%) |
||||||
Eyelid disorders |
3 (3%) |
1 (1%) |
4 (4%) |
1 (1%) |
1 (1%) |
1 (1%) |
3 (3%) |
||||||||
Retinal disorders |
3 (3%) |
4 (4%) |
2 (2%) |
2 (2%) |
1 (1%) |
12 (12%) |
1 (1%) |
2 (2%) |
3 (3%) |
||||||
Vision disorders |
3 (3%) |
1 (1%) |
1 (1%) |
5 (5%) |
1 (1%) |
2 (2%) |
1 (1%) |
4 (4%) |
|||||||
3 (3%) |
1 (1%) |
1 (1%) |
5 (5%) |
1 (1%) |
1 (1%) |
2 (2%) |
|||||||||
In the header, N represents the number of patients. | |||||||||||||||
Percentages reflect the proportion of patients whose maximum AE grade was as indicated. | |||||||||||||||
Alternative 2: AE minimum grades by SOC and term, stratified by arm
The function handles many more arguments. For example, you can use
sort_by_count=FALSE to sort alphabetically by
group1 instead of by count, and total=FALSE
and showNA=FALSE to remove the “Total” and “NA”
columns.
ae_table_soc(data_ae=ae, data_pat=enrolres, measure="sup", arm="arm", group1="aeterm",
sort_by_count=FALSE, total=FALSE, showNA=FALSE) %>%
as_flextable() %>%
delete_rows(i=11:103) %>%
add_footer_lines("In the header, N represents the number of patients.") %>%
add_footer_lines("Percentages reflect the proportion of patients who had at least one AE higher or equal to the indicated grade.")Control (N=100) |
Treatment (N=100) |
|||||||||
|---|---|---|---|---|---|---|---|---|---|---|
AE Term (HLGT) |
G1 |
G2 |
G3 |
G4 |
G5 |
G1 |
G2 |
G3 |
G4 |
G5 |
Adrenal gland disorders |
2 (2%) |
1 (1%) |
||||||||
Anxiety disorders |
1 (1%) |
3 (3%) |
2 (2%) |
1 (1%) |
||||||
Arthritis and joint disorders |
3 (3%) |
3 (3%) |
1 (1%) |
1 (1%) |
1 (1%) |
|||||
Autoimmune disorders |
1 (1%) |
4 (4%) |
3 (3%) |
2 (2%) |
1 (1%) |
|||||
Bacterial infectious disorders |
2 (2%) |
|||||||||
Benign neoplasms |
8 (8%) |
6 (6%) |
1 (1%) |
1 (1%) |
2 (2%) |
2 (2%) |
||||
Bile duct disorders |
3 (3%) |
1 (1%) |
4 (4%) |
2 (2%) |
||||||
Bladder disorders |
1 (1%) |
1 (1%) |
1 (1%) |
1 (1%) |
||||||
Blood analyses |
3 (3%) |
1 (1%) |
1 (1%) |
|||||||
Bone disorders |
2 (2%) |
2 (2%) |
2 (2%) |
1 (1%) |
1 (1%) |
2 (2%) |
2 (2%) |
1 (1%) |
||
No Declared AE |
||||||||||
In the header, N represents the number of patients. | ||||||||||
Percentages reflect the proportion of patients who had at least one AE higher or equal to the indicated grade. | ||||||||||