forked from elong0527/r4csr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtlf-overview.Rmd
339 lines (257 loc) · 12.3 KB
/
tlf-overview.Rmd
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# (PART) Delivering TLFs in CSR {-}
# Overview {#tlf-overview}
```{r, include=FALSE}
source("common.R")
```
## Background
In clinical trials, a critical step is to submit trial results to regulatory agencies.
[Electronic Common Technical Document (eCTD)](https://en.wikipedia.org/wiki/Electronic_common_technical_document)
has become a worldwide regulatory submission standard format.
For example, the United States Food and Drug Administration (US FDA) requires
new drug applications and biologics license applications
[must be submitted using the eCTD format](https://www.fda.gov/drugs/electronic-regulatory-submission-and-review/electronic-common-technical-document-ectd).
The Clinical Data Interchange Standards Consortium (CDISC) provides a
[pilot project following ICH E3 guidance](https://bitbucket.cdisc.org/projects/CED/repos/sdtm-adam-pilot-project/browse).
Within eCTD, clinical study reports (CSRs) are located at module 5.
[ICH E3 guidance](https://www.ich.org/page/efficacy-guidelines) provides
a compilation of the structure and content of clinical study reports.
A typical CSR contains full details on the methods and results of an individual clinical study.
In support of the statistical analysis, a large number of tables, listings, and figures are
incorporated into the main text and appendices.
In the CDISC pilot project, an
[example CSR](https://bitbucket.cdisc.org/projects/CED/repos/sdtm-adam-pilot-project/browse/updated-pilot-submission-package/900172/m5/53-clin-stud-rep/535-rep-effic-safety-stud/5351-stud-rep-contr/cdiscpilot01/cdiscpilot01.pdf)
is also provided. If you are interested in more examples of clinical study reports,
you can go to the [European Medicines Agency (EMA) clinical data website](https://clinicaldata.ema.europa.eu/web/cdp/home).
Building CSRs is teamwork between clinicians, medical writers, statisticians, statistical programmers,
and other relevant specialists such as experts on biomarkers.
Here, we focus on the work and deliverables completed by statisticians and statistical programmers.
In an organization, they commonly work together to
define, develop, validate and deliver tables, listings, and figures (TLFs) required for a CSR to
summarize the efficacy and/or safety of the pharmaceutical product.
Microsoft Word is widely used to prepare CSR in the pharmaceutical industry.
Therefore, `.rtf`, `.doc`, `.docx` are commonly used formats in their deliverables.
In this chapter, our focus is to illustrate how to create tables, listings, and figures (TLFs) in RTF format
that is commonly used in a CSR. The examples are in compliance with the
[FDA's Portable Document Format (PDF) Specifications](https://www.fda.gov/media/76797/download).
::: {.rmdnote}
FDA's PDF specification is a general reference. Each organization can define
more specific TLF format requirements that can be different from the examples in this book.
:::
## Structure and content
In the rest of this chapter, we are following the
[ICH E3 guidance](https://database.ich.org/sites/default/files/E3_Guideline.pdf)
on the structure and content of clinical study reports.
In a CSR, most of TLFs are located in
- Section 10: Study participants
- Section 11: Efficacy evaluation
- Section 12: Safety evaluation
- Section 14: Tables, listings, and figures referrals but not included in the text
- Section 16: Appendices
## Datasets
We used publicly available CDISC pilot
[study data located in the CDISC Bitbucket repository](https://bitbucket.cdisc.org/projects/CED/repos/sdtm-adam-pilot-project/browse/updated-pilot-submission-package/900172/m5/datasets/cdiscpilot01/analysis/adam/datasets).
For simplicity, we have downloaded all these datasets into the `data-adam/`
folder of this project and converted them from the `.xpt` format to
the `.sas7bdat` format.
The dataset structure follows
[CDISC Analysis Data Model (ADaM)](https://www.cdisc.org/standards/foundational/adam).
## Tools
In this part, we mainly use the R packages below to illustrate
how to deliver TLFs in a CSR.
- [tidyverse](https://www.tidyverse.org/): prepare datasets ready for reporting.
- [r2rtf](https://merck.github.io/r2rtf/): create RTF outputs
::: {.rmdnote}
There are other R packages to create TLFs in ASCII, RTF and Word format.
For example, `rtables`, `huxtable`, `pharmaRTF`, `gt`, `officer`, `flextable` etc.
Here we focus on `r2rtf` to illustrate the concept.
Readers are encouraged to explore other R packages to find the proper tools to fit your purpose.
:::
### tidyverse
`tidyverse` is a collection of R packages to simplify the workflow to manipulate,
visualize and analyze data in R.
Those R packages share
[the tidy tools manifesto](https://cran.r-project.org/web/packages/tidyverse/vignettes/manifesto.html)
and are easy to use for interactive data analysis.
RStudio provided outstanding [cheatsheets](https://www.rstudio.com/resources/cheatsheets/)
and [tutorials](https://github.com/rstudio-education/remaster-the-tidyverse) for `tidyverse`.
There are also books to introduce `tidyverse`.
We assume the reader have experience in using `tidyverse` in this book.
- [The tidyverse cookbook](https://rstudio-education.github.io/tidyverse-cookbook/)
- [R for Data Science](https://r4ds.had.co.nz/)
### r2rtf
`r2rtf` is an R package to create production-ready tables and figures in RTF format.
This R package is designed to
- provide simple "verb" functions that correspond to each component of a table,
to help you translate a data frame to a table in an RTF file;
- enable pipes (`%>%`);
- focus on the **table format** only.
Data manipulation and analysis shall be handled by other R packages (e.g., `tidyverse`).
Before creating an RTF table, we need to
- figure out the table layout;
- split the layout into small tasks in the form of a computer program;
- execute the program.
We provide a brief introduction of `r2rtf` and show how to transfer
data frames into table, listing, and figures (TLFs).
Other extended examples and features are covered on the
[`r2rtf` package website](https://merck.github.io/r2rtf/articles/index.html).
To explore the basic RTF generation verbs in `r2rtf`,
we will use the dataset `r2rtf_adae` saved in the `r2rtf` package.
This dataset contains adverse events (AEs) information from a clinical trial.
We will begin by loading the packages:
```{r}
library(dplyr) # Manipulate data
library(tidyr) # Manipulate data
library(r2rtf) # Reporting in RTF format
```
Below is the meaning of relevant variables.
More information can be found on the help page of the dataset (`?r2rtf_adae`)
In this example, we consider three variables:
- USUBJID: Unique Subject Identifier
- TRTA: Actual Treatment
- AEDECOD: Dictionary-Derived Term
```{r}
r2rtf_adae %>%
select(USUBJID, TRTA, AEDECOD) %>%
head(4)
```
`dplyr` and `tidyr` packages within `tidyverse` are used
for data manipulation to create a data frame
that contains all the information we want to add in an RTF table.
```{r}
tbl <- r2rtf_adae %>%
count(TRTA, AEDECOD) %>%
pivot_wider(names_from = TRTA, values_from = n, values_fill = 0)
tbl %>% head(4)
```
Now we have a dataset `tbl` in preparing the final RTF table.
`r2rtf` aims to provide one function for each type of table layout.
Commonly used verbs include:
- `rtf_page()`: RTF page information
- `rtf_title()`: RTF title information
- `rtf_colheader()`: RTF column header information
- `rtf_body()`: RTF table body information
- `rtf_footnote()`: RTF footnote information
- `rtf_source()`: RTF data source information
All these verbs are designed to enable the usage of pipes (`%>%`).
A full list of all functions can be found in the
[r2rtf package function reference manual](https://merck.github.io/r2rtf/reference/index.html).
A minimal example below illustrates how to combine verbs using pipes to create an RTF table.
- `rtf_body()` is used to define table body layout.
- `rtf_encode()` transfers table layout information into RTF syntax.
- `write_rtf()` save RTF encoding into a file with file extension `.rtf`
```{r}
head(tbl) %>%
rtf_body() %>% # Step 1 Add table attributes
rtf_encode() %>% # Step 2 Convert attributes to RTF encode
write_rtf("tlf/intro-ae1.rtf") # Step 3 Write to a .rtf file
```
```{r, include=FALSE}
rtf2pdf("tlf/intro-ae1.rtf")
```
```{r, out.width = "100%", out.height = "400px", echo = FALSE, fig.align = "center"}
knitr::include_graphics("tlf/intro-ae1.pdf")
```
If we want to adjust the width of each column to
provide more space to the first column,
this can be achieved by updating the `col_rel_width` argument
in the `rtf_body()` function.
In this example, the input of `col_rel_width` is a vector
with the same length for the number of columns.
This argument defines the relative width of each column
within a pre-defined total column width.
In this example, the defined relative width is `3:2:2:2`.
Only the ratio of `col_rel_width` is used.
Therefore it is equivalent to use `col_rel_width = c(6, 4, 4, 4)`
or `col_rel_width = c(1.5, 1, 1, 1)`.
```{r}
head(tbl) %>%
rtf_body(col_rel_width = c(3, 2, 2, 2)) %>%
# define relative width
rtf_encode() %>%
write_rtf("tlf/intro-ae2.rtf")
```
```{r, include=FALSE}
rtf2pdf("tlf/intro-ae2.rtf")
```
```{r, out.width = "100%", out.height = "400px", echo = FALSE, fig.align = "center"}
knitr::include_graphics("tlf/intro-ae2.pdf")
```
In the previous example, we found the issue of a misaligned column header.
We can fix the issue by using the `rtf_colheader()` function.
In `rtf_colheader()`, the `colheader` argument is used to provide the content of the column header.
We use `"|"` to separate the columns.
In the example below, `"Adverse Events | Placebo | Xanomeline High Dose | Xanomeline Low Dose"`
define a column header with 4 columns.
```{r}
head(tbl) %>%
rtf_colheader(
colheader = "Adverse Events | Placebo | Xanomeline High Dose | Xanomeline Low Dose",
col_rel_width = c(3, 2, 2, 2)
) %>%
rtf_body(col_rel_width = c(3, 2, 2, 2)) %>%
rtf_encode() %>%
write_rtf("tlf/intro-ae3.rtf")
```
```{r, include=FALSE}
rtf2pdf("tlf/intro-ae3.rtf")
```
```{r, out.width = "100%", out.height = "400px", echo = FALSE, fig.align = "center"}
knitr::include_graphics("tlf/intro-ae3.pdf")
```
In `rtf_*()` functions such as `rtf_body()`, `rtf_footnote()`,
the `text_justification` argument is used to align text.
Default is `"c"` for center justification.
To vary text justification by column, use character vector with length of vector equals to
number of columns displayed (e.g., `c("c", "l", "r")`).
All possible inputs can be found in the table below.
```{r}
r2rtf:::justification()
```
Below is an example to make the first column left-aligned and center-aligned for the rest.
```{r}
head(tbl) %>%
rtf_body(text_justification = c("l", "c", "c", "c")) %>%
rtf_encode() %>%
write_rtf("tlf/intro-ae5.rtf")
```
```{r, include=FALSE}
rtf2pdf("tlf/intro-ae5.rtf")
```
```{r, out.width = "100%", out.height = "400px", echo = FALSE, fig.align = "center"}
knitr::include_graphics("tlf/intro-ae5.pdf")
```
In `rtf_*()` functions such as `rtf_body()`, `rtf_footnote()`, etc.,
`border_left`, `border_right`, `border_top`, and `border_bottom` control cell borders.
If we want to remove the top border of `"Adverse Events"` in the header,
we can change the default value `"single"` to `""` in the `border_top` argument, as shown below.
`r2rtf` supports 26 different border types. The details can be found on
the [r2rtf package website](https://merck.github.io/r2rtf/articles/rtf-row.html#border-type).
In this example, we also demonstrate the possibility of adding multiple column headers.
```{r}
head(tbl) %>%
rtf_colheader(
colheader = " | Treatment",
col_rel_width = c(3, 6)
) %>%
rtf_colheader(
colheader = "Adverse Events | Placebo | Xanomeline High Dose | Xanomeline Low Dose",
border_top = c("", "single", "single", "single"),
col_rel_width = c(3, 2, 2, 2)
) %>%
rtf_body(col_rel_width = c(3, 2, 2, 2)) %>%
rtf_encode() %>%
write_rtf("tlf/intro-ae7.rtf")
```
```{r, include=FALSE}
rtf2pdf("tlf/intro-ae7.rtf")
```
```{r, out.width = "100%", out.height = "400px", echo = FALSE, fig.align = "center"}
knitr::include_graphics("tlf/intro-ae7.pdf")
```
In the `r2rtf` R package [get started](https://merck.github.io/r2rtf/articles/r2rtf.html) page,
there are more examples to illustrate how to customize
- title, subtitle
- footnote, data source
- special character
- etc.
Those features will be introduced when we first use them in the rest of the chapters.