---
title: "Exporting in-text tables"
author: "Laure Cougnaud"
date: "`r format(Sys.Date(), '%B %d, %Y')`"
output: 
  rmarkdown::html_document:
    toc: true
    toc_float: true
    toc_depth: 5
    number_sections: true
vignette: >
  %\VignetteIndexEntry{Exporting in-text tables}
  %\VignetteEngine{knitr::rmarkdown}
  \usepackage[utf8]{inputenc}
---

```{r options, echo = FALSE}

library(knitr)
opts_chunk$set(
    echo = TRUE, results = 'markup', warning = FALSE, 
    # stop document execution if error (not the default)
    error = FALSE, 
    message = FALSE, cache = FALSE,
    fig.width = 8, fig.height = 7,
    fig.path = "./figures_vignette/",
    fig.align = 'center')
options(width = 170)
# instead of warn = 0 by default
# include warnings when they occur in the document
options(warn = 1)

```

In this vignette we focus on exporting tables created with the
`inTextSummaryTable` package.

In particular, we will cover

* how to **export tables for specific formats as Word/Powerpoint/Html/R object**
* how to **make your custom aesthetics**
* how to **save tables into separated documents**
* how to set specific **text formatting** (e.g. superscripts/subscripts)
* how to **create multiple tables** at once based on a variable of interest
* how to **create a listing**
* how to **filter and split** exported tables

We assume you are already familiar on how to create tables, otherwise we advise
to first check out the dedicated vignette on how to make tables, available
[here](../doc/inTextSummaryTable-createTables.html)) or accessible with the
commands below.

```{r getVignette, eval = FALSE}

vignette("inTextSummaryTable-createTables", "inTextSummaryTable")

```

We will first create example data sets to show how the exporting functionalities
work. The data sets used are available in the `clinUtils` package.


# Load packages and data


```{r loadPackages}

library(inTextSummaryTable)
library(clinUtils)
library(tools) # toTitleCase

```

```{r loadData}	

# load example data
data(dataADaMCDISCP01)

dataAll <- dataADaMCDISCP01
labelVars <- attr(dataAll, "labelVars")

```

This section creates example data sets used below.

```{r createExampleData}

dataAE <-  subset(dataAll$ADAE, SAFFL == "Y" & TRTEMFL == "Y")
dataAEInterest <- subset(dataAE, AESOC %in% c(
        "INFECTIONS AND INFESTATIONS",
        "GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS"
    )
)

# ensure that order of elements is the one specified in 
# the corresponding numeric variable
dataAEInterest$TRTA <- reorder(dataAEInterest$TRTA, dataAEInterest$TRTAN)
dataAEInterest$AESEV <- factor(dataAEInterest$AESEV, levels = c("MILD", "MODERATE"))

dataTotalAE <- subset(dataAll$ADSL, TRT01A != "Placebo")
# should contain columns specified in 'colVar'
dataTotalAE$TRTA <- dataTotalAE$TRT01A 


```

# Output formats {#outputFormat}

The default exported format is **`flextable`**, which is **suitable for Word/PowerPoint** documents.

Alternatively, a table can be exported as **datatable interactive table for html reports**, 
or as a **data frame in R**.

The `outputType` parameter specifies the output format of the summary statistics
table.

## Static table for Word/Powerpoint

### General format

To get the table in a format **suitable for _Word_/_Powerpoint_** documents, the
**outputType** parameter should be set to **'flextable'** (the default).

```{r outputType-flextable}

summaryTableFt <- getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    title = "Table: Adverse Events by System Organ Class and Preferred Term",
    footer = c(
        "N = number of subjects in the data; n = number of subjects with observation",
        paste("Denominator for percentage calculations is the total number of subjects",
            "per treatment group in the safety population"
        )
    ),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    outputType = "flextable"
)
class(summaryTableFt)
summaryTableFt

```

The object `summaryTableFt` is a **flextable object**.

This is available through the [`flextable` R
package](https://cran.r-project.org/package=flextable) (see `?flextable`).

When printed into the R console, a flextable object is displayed in the
internet browser. However, the
`summaryTableFt` object can be inserted within a `rmarkdown` document by
printing it in the specified document chunk, providing that the following
system requirement are satisfied:

* `flextable` version >= 0.4.7
* for a `docx` document (`output_type`):
  [pandoc](https://pandoc.org/installing.html) version >= 2.0 (see [`rmarkdown`
  documentation for
  Word](https://bookdown.org/yihui/rmarkdown/word-document.html))
* for `pptx` document: [pandoc](https://pandoc.org/installing.html) version >=
  2.4 (see [`rmarkdown` documentation for
  Powerpoint](https://bookdown.org/yihui/rmarkdown/powerpoint-presentation.html))

A `rmarkdown` chunk can contains only one `flextable` object. To include a list
of `flextable` in a `rmarkdown` document, the function `knitPrintListObjects` of
the `clinUtils` package can be used.

### Style: report or presentation

The table can be styled via the **`style`** parameter. This parameter affects
the fontsize, font family, color of the text and background, dimensions of the
table.

Other specific parameters can be used to export the table as landscape
(`landscape`), specify custom margins (`margin`), row indent (`rowVarPadBase`),
font size and family (`fontsize` and `font`).

By default, the table is styled for a **CSR report**.

```{r style-report}

getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    title = "Table: Adverse Events by System Organ Class and Preferred Term",
    footer = c(
        "N = number of subjects with data; n = number of subjects with this observation",
        paste("Denominator for percentage calculations is the total number of subjects",
            "per treatment group in the safety population"
        )
    ),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)")
)

```

The table can also be styled for a **presentation**.

Note that the default dimension of a table printed in a Powerpoint document
follows the standard 4:3 size (7.5 x 10 inches).

If you wish to set the dimension for a Widescreen document, it is possible to
set a global option for this. Please, check out the section "Custom aesthetics".

```{r style-presentation}

getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    title = "Table: Adverse Events by System Organ Class and Preferred Term",
    footer = c(
        "N = number of subjects with data; n = number of subjects with this observation",
        paste("Denominator for percentage calculations is the total number of subjects",
            "per treatment group in the safety population"
        )
    ),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    style = "presentation"
)

```


## Interactive table for html

The summary statistics table is exported as an interactive table by setting the
parameter: **`outputType`** to **'DT'**.

A `datatable` object, created with the
[DT](https://CRAN.R-project.org/package=DT) R package is created.

Interactivity includes the functionalities to:

* filter the table
* order columns
* export the table (or a subset of this)
* include custom interactivity e.g. the possibility to have expandable
  rows/columns, see patient profiles inclusion in the medical monitoring report

Such table can be included in a _html_ `rmarkdown` report.

The interactive table can be further customized 
by setting options specific to this output (see `clinUtils::getClinDT`).

Please note that the interactive table is only created if Pandoc is available.

```{r outputType-DT, eval = rmarkdown::pandoc_available()}

getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    title = "Table: Adverse Events by System Organ Class and Preferred Term",
    footer = c(
        "N = number of subjects in the data; n = number of subjects with observation",
        paste("Denominator for percentage calculations is the total number of subjects",
            "per treatment group in the safety population"
        )
    ),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    outputType = "DT",
	## DT-specific options
	buttons = c() # remove all export buttons
)

```

## Data frames for R

The summary statistics table can be stored as a R object.

Note that the exported `data.frame`s contains _attributes_ that indicate which
statistics are used, which row variables/column variables are to be shown and
how etc.

### Final table

The summary statistics data displayed in the final table object can be exported
as an R `data.frame`.

In this case the **`outputType`** should be set to **`data.frame`**.

```{r outputType-dataframe}

summaryTable <- getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    title = "Table: Adverse Events by System Organ Class and Preferred Term",
    footer = c(
        "N = number of subjects in the data; n = number of subjects with observation",
        paste("Denominator for percentage calculations is the total number of subjects",
            "per treatment group in the safety population"
        )
    ),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    style = "presentation",
    outputType = "data.frame"
)
print(summaryTable, split.table = Inf)
```

### Full table in long format

The table with all the computed summary statistics, the specified set of
statistics of interest and all row/column variables stored in a long format is
available by using the **`outputType`** parameter to **'data.frame-base'**.

This format is typically of interest to run quality checks of the computed
summary statistics in comparison with e.g. Table/Listing/Figures, or to compare
the statistics computed between batches of the data.

```{r outputType-dataframe-base}

summaryTableAll <- getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    title = "Table: Adverse Events by System Organ Class and Preferred Term",
    footer = c(
        "N = number of subjects in the data; n = number of subjects with observation",
        paste("Denominator for percentage calculations is the total number of subjects",
            "per treatment group in the safety population"
        )
    ),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    style = "presentation",
    outputType = "data.frame-base"
)
print(summaryTableAll, split.table = Inf)
```

## Differences between the format

Most of the functionalities and default parameters are the same between the
`flextable` and `DT` format, at the exception of:
 
* for the `DT` format, by default the variables and statistics are included
      in different columns: `rowVarInSepCol` is `rowVar` and `statsLayout` is
      set to 'col'
* for the `flextable` format, by default the row variables and statistics
      are nested:   `rowVarInSepCol` is set to: 'NULL' and the `statsLayout` is
      set to 'row'

# Custom aesthetics

The `inTextSummaryTable` contains functionalities to set the aesthetics of the
tables.

Those **aesthetics are set through global options**.

This has the main advantage that if you wish to change the default color scheme,
it is possible to set your preferences only once at the beginning of the R
script or Rmd document.

When loading the package, the global options for palettes get automatically
defined into the R session. If you wish to change the default colors, you
can apply your preferences by changing the global options. 

The `inTextSummaryTable` package has the following options for table aesthetics:

* **`inTextSummaryTable.colors.table.presentation`**

* **`inTextSummaryTable.pageDim.presentation`**

The first option sets custom colors for a table in a presentation mode, the
last one defines the page dimension of a Powerpoint when exporting a table.

Note that **the options have to be defined after loading the package**. This
because when loading the package, the default global options for palettes will
overwrite the custom palettes.

## Colors

As you may have already noticed if you have read the vignette till here, by
default, the reporting format makes tables with a black text on a white
background. On the contrary, the presentation format creates tables with a blue
header and white text, whereas the body is grey with black text.

If you wish to define a personal color scheme, a named vector can be created and
passed to the `options`, as shown below.

Colors can be provided in hexadecimals or in `rgb` specification. In the example
we use hexadecimals just for convenience.

Note that the `bodyBackground1` and `bodyBackground2` allow to have alternating
row colors.

```{r aesthetics-changeReportingOptions}

# create named vector
customColorTable <- c(
    # black text in the header
    'header' = "#000000",
    # green background in the header
    'headerBackground' = "#74D055FF",
    # black text in the body
    'body' = "#000000", 
    # yellow background for all rows
    'bodyBackground1' = "#FDE725FF",
    'bodyBackground2' = "#FDE725FF",
    # black footer
    'footer' = "#000000",
    # white footer background
    'footerBackground' = "#FFFFFF",
    # black line for footer
    'line' = "#000000"
)
# set options
options(inTextSummaryTable.colors.table.presentation = customColorTable)
# create the table on a dummy data set
getSummaryStatisticsTable(
    data = data.frame(USUBJID = c(1, 2)),
    style = "presentation" 
)

```

## Dimension of the page

By default, the `inTextSummaryTable` ships with a default PowerPoint in the
standard 4:3 size (7.5 x 10 inches).

However, it is often common to create a PowerPoint template with **Widescreen
size** of 16:9 which consistts of 7.50 x 13.32 inches.

Therefore, it possible to accomodate such widescreen size by providing

```{r aesthetics-changeDimPageOptions}

# set custom dimension of page for presentation
# in this example, the dimension is the widescreen size
pageDimCustom <- c(7.5, 13.32)
options(inTextSummaryTable.pageDim.presentation = pageDimCustom)
getOption("inTextSummaryTable.pageDim.presentation")

```

## Further info on asthetics

For further information about the aesthetics settings of
the package, a dedicated vignette is available at 

```{r getVignetteAesthetics, eval = FALSE}

vignette("inTextSummaryTable-aesthetics", "inTextSummaryTable")

```

## Set back default palettes

There is always to possibility to switch back to the default palettes of the
package:

```{r aesthetics-backDefaultPalettes}

options(inTextSummaryTable.colors.table.presentation = tableColorsPresentation)

```


# Export table to a separated file

The table can be exported to a different file by specifying a file name in the
**`file`** parameter. 

Possible formats are:

* **txt**: the raw base table is exported to a text file. This format can be
  used e.g. to run quality checks with reference Table/Listings/Figures.
* **docx**: the formatted table is exported to a Word document. Such format is
  typically of interest to share the tables to medical writers, to be
  imported directly into a Statistical Analysis Plan (if `style = 'report'`).
* **html**: an interactive table is exported to the specified html file

```{r file, eval = FALSE}

# export table to a Word document
summaryTableFt <- getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    file = file.path("tables_CSR", "summaryTable-AEs.docx")
)

# export interactive table to a html document
summaryTableFt <- getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    file = file.path("tables_CSR", "summaryTable-AEs.html")
)

# export table in raw format to a text file
summaryTableFt <- getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    file = file.path("tables_CSR", "summaryTable-AEs.txt")
)

# export to multiple formats at once
summaryTableFt <- getSummaryStatisticsTable(
    data = dataAEInterest,
    rowVar = c("AESOC", "AEDECOD"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    dataTotal = dataTotalAE,
    labelVars = labelVars,
    file = file.path("tables_CSR",
        c("summaryTable.txt", "summaryTable.docx", "summaryTable.html")
    )
)

```

# Export table of pre-computed summary statistics

To create a table in a similar format as the in-text tables created by the
package, from pre-computed summary statistics (e.g. from CRO or from a different
software as _SAS_) the function **`exportSummaryStatisticsTable`** can be used.

This function takes as input a **`data.frame` in long format** that should
contain the summary statistics.

The long format should be such that the

* statistic value (`statsVar`)
* statistic type (if multiple), grouping row and columns (`rowVar` and `colVar`)

are both stored as different columns in the `data.frame`.

If the column headers should contain total number of subjects, the corresponding
counts should be stored in records with the column `isTotal` set to TRUE.

```{r export}

dataDIABP <- subset(
	dataAll$ADVS, 
	SAFFL == "Y" & ANL01FL == "Y" &
	PARAMCD == "DIABP" & 
	AVISIT %in% c("Baseline", "Week 6") &
	ATPT == "AFTER LYING DOWN FOR 5 MINUTES"
)

# create example of data.frame containing statistics of interest
statsEff <- sapply(c("AVAL", "CHG"), function(var) {
      
      getStats(
          type = c("n", "mean (se)", "median (range)"),
          x = dataDIABP[[var]]
      )
      
    }, simplify = FALSE)

summaryTable <- computeSummaryStatisticsTable(
    data = dataDIABP,
    colVar = c("TRTP", "AVISIT"),
    var = c("AVAL", "CHG"), varGeneralLab = "",
    stats = statsEff,
    labelVars = labelVars
)

# format df with statistics to in-text table format
export(
    summaryTable = summaryTable,
    statsVar = c("n", "Mean (SE)", "Median (range)"),
    rowVar = "variable", rowVarLab = "Statistic",
    colVar = c("TRTP", "AVISIT"),
    colHeaderTotalInclude = TRUE,
    labelVars = simpleCap(tolower(labelVars[c("AVAL", "CHG")])),
    title = toTitleCase(
		"Table: Diastolic Blood Pressure (mmHg) statistics"
    )
)

```

# Text formatting

Specific formatted text can be specified for the `flextable` output type only.

## Superscript/subscript

Superscript and subscript are specified via the special text pattern as `a^{b}`
and `a_{b}` respectively.

To use a superscript or a subscript in the table, the text should be formatted
as: `text^{superscript}` or `text_{subscript}`.

This is for example useful to reference additional informations in a specific
footnote or specify custom variable labels.

```{r summaryTable-PP-rowVarWithLabel-rowVarLab-superscript}

dataSL <- subset(dataAll$ADSL, SAFFL == "Y")

varsSL <- c("AGE", "WEIGHTBL", "BMIBL")
labelVars[varsSL] <- c(
    "Age",
    "Weight_{t}",
    "BMI (kg/m^{2})"
)

getSummaryStatisticsTable(
    data = dataSL, 
    var = varsSL,  
    stats = getStats("n (%"),
    labelVars = labelVars,
    fontsize = 16,
    title = toTitleCase("Demographic data (Safety Analysis Set)")
)

```

## Bold and greek letters

Specific cells of the table can be highlight in bold by using the syntax:
`bold{}` in the `stats` or `statsExtra` function.

This highlighting may depend:

* on a additional variable via the `statsExtra` parameter:  
for example:
  `statsExtra <- function(data)   with(data, ifelse(ANRIND != "N", paste0("bold{", toString(AVAL), "}"), toString(AVAL))`
* on the values of computed statistics, via the `stats` parameter

Greek letters are included as they are in the table.

```{r summaryTable-PP-rowVarWithLabel-rowVarLab-bold}

getSummaryStatisticsTable(
    data = dataSL, 
    var = varsSL,  
    stats = list(
		expression(paste0(
			ifelse(statMean > statMedian, 
				paste0("bold{", roundHalfUpTextFormat(statMean, 1), "}"), 
				roundHalfUpTextFormat(statMean, 1)
			), 
			"\n(", 
				roundHalfUpTextFormat(statSE, 2),")")
        )
    ),
    labelVars = labelVars,
    fontsize = 12,
    title = toTitleCase("Demographic data (Safety Analysis Set)")
)

```

# Create multiple tables by a variable

Multiple tables can be created for each element of a variable in the dataset  by
specifying the name of the variable in the argument **`byVar`**.  
 
A list of final summary table can be included into a `rmarkdown`  document with
the `knitPrintListObjects`. 

Please note that the following chunk option should be used:
**`results = 'asis'`**.

For example, AE tables are created for each treatment:

```{r byVar, results = "asis"}

summaryTableList <- getSummaryStatisticsTable(
    data = subset(dataAE, TRTEMFL == "Y"),
    rowVar = c("AESOC", "AEDECOD"),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    colVar = "TRTA",
    byVar = "TRTA",
    stats = getStats("n (%)"),
    labelVars = labelVars,
    title = "Table: Treatment-Emergent adverse events"
)

# print the list of tables in the rmarkdown document
clinUtils::knitPrintListObjects(summaryTableList) 

```


# Listing

Listing in a similar format as the in-text summary table is created via the `getListing` function.

```{r getListing}

varsListing <- c(
	"USUBJID", "AEBODSYS", "AEDECOD", "TRTA", 
	"AESEV", "AESER", "ASTDY", "AENDY"
)

dataListing <- subset(dataAE, TRTEMFL == "Y" & AESEV == "SEVERE")
dataListing <- dataListing[, varsListing]
colnames(dataListing) <- getLabelVar(var = varsListing, labelVars = labelVars)

getListing(
	data = dataListing, 
	title = "Listing of treatment-emergent severe adverse events",
	includeRownames = FALSE
)

```

# Filter records in a table

If only a subset of the records should be displayed in the final table, a custom
filtering functions is specified via the **`filterFct`** parameter.

```{r countTable-AE-filterFct}

library(plyr)

# SOC with AE terms with at least 2 subjects
getSummaryStatisticsTable(
    data = subset(dataAE, TRTEMFL == "Y"),
    rowVar = c("AESOC", "AEDECOD"),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    filterFct = function(x)
      ddply(x, "AESOC", function(y)
            if(any(y$statN >= 2))	y			
      ),
    labelVars = labelVars,
    title = paste(
        "Table: Adverse Events by System Organ Class and",
        "Preferred Term with at least 2 patients in System Organ Class"
    )
)

# AE term with at least one term with more than 70% in the treatment
getSummaryStatisticsTable(
    data = subset(dataAE, TRTEMFL == "Y"),
    rowVar = c("AESOC", "AEDECOD"),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    filterFct = function(x)
      ddply(x, "AEDECOD", function(xTerm) {
            if(any(xTerm$statPercN >= 70))	xTerm		
          }),
    labelVars = labelVars,
    title = "Table: Adverse Events by System Organ Class and Preferred Term with at least 70% patients"
)

```

Note: to help the creation of this filtering function, the displaying data
could be extracted first via the `computeSummaryStatisticsTable` function
(instead of creating directly the in-text table via the
`getSummaryStatisticsTable`), and then used to define the `filterFct` parameter.

```{r countTable-AE-filterFct- details}

x <- computeSummaryStatisticsTable(
    data = subset(dataAE, TRTEMFL == "Y"),
    rowVar = c("AESOC", "AEDECOD"),
    rowVarLab = c('AESOC' = "TEAE by SOC and Preferred Term\nn (%)"),
    colVar = "TRTA",
    stats = getStats("n (%)"),
    labelVars = labelVars
)
head(x)

# for specific AEDECOD
xTerm <- subset(x, AEDECOD == "MYOCARDIAL INFARCTION")
# identify the record for treated patient:
subset(xTerm, grepl("Placebo", TRTA))
# keep all records (placebo + treatment) if percentage if higher than 20%:
# if no 'else' condition, nothing (NULL) is returned:
if(subset(xTerm, grepl("Placebo", TRTA))$statPercN >= 20)	xTerm
# across all AE terms:
ddply(x, "AEDECOD", function(xTerm)
      if(subset(xTerm, grepl("Placebo", TRTA))$statPercN >= 20)	xTerm
)

# format it as a function and pass it to the 'filterFct' parameter
```

# Appendix

## Session information

```{r includeSessionInfo, echo = FALSE, results = "asis"}
print(sessionInfo())
```