-
Notifications
You must be signed in to change notification settings - Fork 34
/
tlf-disposition.qmd
190 lines (155 loc) · 5.94 KB
/
tlf-disposition.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# Disposition {#sec-disposition}
```{r, include=FALSE}
source("_common.R")
```
Following [ICH E3 guidance](https://database.ich.org/sites/default/files/E3_Guideline.pdf),
a summary table needs to be provided to include all participants who entered the study in Section 10.1, Disposition of Participants.
The disposition of participants table reports the numbers of participants who were randomized,
and who entered and completed each phase of the study.
In addition, the reasons for all post-randomization discontinuations,
grouped by treatment and by major reason (lost to follow-up, adverse event, poor compliance, etc.) are reported.
```{r}
library(haven) # Read SAS data
library(dplyr) # Manipulate data
library(tidyr) # Manipulate data
library(r2rtf) # Reporting in RTF format
```
In this chapter, we show how to create a typical disposition table.
```{r, out.width = "100%", out.height = if (knitr::is_html_output()) "400px", echo = FALSE, fig.align = "center"}
knitr::include_graphics("tlf/tbl_disp.pdf")
```
The first step is to read in the relevant datasets into R.
For a disposition table, all the required information is saved in a Subject-level Analysis Dataset (ADSL).
This dataset is provided in `sas7bdat` format, which is a SAS data format currently used in many clinical trial analysis and reporting.
The `haven` package is able to read the dataset, while maintaining its attributes (e.g., variable labels).
```{r}
adsl <- read_sas("data-adam/adsl.sas7bdat")
```
The following variables are used in the preparation of a simplified disposition of participants table:
- USUBJID: unique subject identifier
- TRT01P: planned treatment
- TRT01PN: planned treatment numeric encoding
- DISCONFL: discontinued from study flag
- DCREASCD: discontinued from study reason coded
```{r}
adsl %>% select(USUBJID, TRT01P, TRT01PN, DISCONFL, DCREASCD)
```
In the code below, we calculate the number of participants in the analysis population by treatment arms.
```{r}
n_rand <- adsl %>%
group_by(TRT01PN) %>%
summarize(n = n()) %>%
pivot_wider(
names_from = TRT01PN,
names_prefix = "n_",
values_from = n
) %>%
mutate(row = "Participants in population")
n_rand
```
```{r}
n_disc <- adsl %>%
group_by(TRT01PN) %>%
summarize(
n = sum(DISCONFL == "Y"),
pct = formatC(n / n() * 100,
digits = 1, format = "f", width = 5
)
) %>%
pivot_wider(
names_from = TRT01PN,
values_from = c(n, pct)
) %>%
mutate(row = "Discontinued")
n_disc
```
In the code below, we calculate the number and percentage of
participants who completed/discontinued the study for different reasons by treatment arms.
```{r}
n_reason <- adsl %>%
group_by(TRT01PN) %>%
mutate(n_total = n()) %>%
group_by(TRT01PN, DCREASCD) %>%
summarize(
n = n(),
pct = formatC(n / unique(n_total) * 100,
digits = 1, format = "f", width = 5
)
) %>%
pivot_wider(
id_cols = DCREASCD,
names_from = TRT01PN,
values_from = c(n, pct),
values_fill = list(n = 0, pct = " 0.0")
) %>%
rename(row = DCREASCD)
n_reason
```
In the code below, we calculate the number and percentage of participants who complete the study by treatment arms.
We split `n_reason` because we want to customize the row order of the table.
```{r}
n_complete <- n_reason %>%
filter(row == "Completed")
n_complete
```
In the code below, we calculate the numbers and percentages of participants who discontinued the study for different reasons by treatment arms.
For display purpose, `paste0(" ", row)` is used to add leading spaces to produce indentation in the final report.
```{r}
n_reason <- n_reason %>%
filter(row != "Completed") %>%
mutate(row = paste0(" ", row))
n_reason
```
Now we combine individual rows into one table for reporting purpose.
`tbl_disp` is used as input for r2rtf to create final report.
```{r}
tbl_disp <- bind_rows(n_rand, n_complete, n_disc, n_reason) %>%
select(row, ends_with(c("_0", "_54", "_81")))
tbl_disp
```
In the below code, formatting of the final table is defined.
Items that were not discussed in the previous sections, are highlighted below.
The `rtf_title` defines table title.
We can provide a vector for the title argument.
Each value is a separate line.
The format can also be controlled by providing a vector input in text format.
```{r}
tbl_disp %>%
# Table title
rtf_title("Disposition of Participants") %>%
# First row of column header
rtf_colheader(" | Placebo | Xanomeline Low Dose| Xanomeline High Dose",
col_rel_width = c(3, rep(2, 3))
) %>%
# Second row of column header
rtf_colheader(" | n | (%) | n | (%) | n | (%)",
col_rel_width = c(3, rep(c(0.7, 1.3), 3)),
border_top = c("", rep("single", 6)),
border_left = c("single", rep(c("single", ""), 3))
) %>%
# Table body
rtf_body(
col_rel_width = c(3, rep(c(0.7, 1.3), 3)),
text_justification = c("l", rep("c", 6)),
border_left = c("single", rep(c("single", ""), 3))
) %>%
# Encoding RTF syntax
rtf_encode() %>%
# Save to a file
write_rtf("tlf/tbl_disp.rtf")
```
```{r, include=FALSE}
rtf2pdf("tlf/tbl_disp.rtf")
```
```{r, out.width = "100%", out.height = if (knitr::is_html_output()) "400px", echo = FALSE, fig.align = "center"}
knitr::include_graphics("tlf/tbl_disp.pdf")
```
The procedure to generate a disposition table can be summarized as follows:
- Step 1: Read subject level data (i.e., `adsl`) into R.
- Step 2: Count participants in the analysis population and name the dataset `n_rand`.
- Step 3: Calculate the number and percentage of participants who discontinued the study by treatment arm, and name the dataset `n_disc`.
- Step 4: Calculate the numbers and percentages of participants who discontinued the study for different reasons by treatment arm,
and name the dataset `n_reason`.
- Step 5: Calculate the number and percentage of participants who completed the study by treatment arm, and name the dataset `n_complete`.
- Step 6: Bind `n_rand`, `n_disc`, `n_reason`, and `n_complete` by row.
- Step 7: Write the final table to RTF