--- title: "reportRmd Package" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{reportRmd Package} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- # Overview reportRmd is a package designed to facilitate the reporting of common statistical outputs easily in RMarkdown documents. The package supports pdf, html and word output without any changes to the body of the report. The main features are Table 1 style summaries, combining multiple univariate regression models into a single table, tidy multivariable model output and combining univariate and multivariable regressions into a single table. Single table summaries of median survival times and survival probabilities are also provided. A highly customisable survival curve function, based on ggplot2 can be used to create publication-quality plots. Visualisation plots are also available for bivariate relationships and logistic regression models. A word of caution: The reportRmd package is designed to facilitate statistical reporting and does not provide any checks regarding the suitability of the models fit. ```{r setup, include=FALSE} library(reportRmd) knitr::opts_chunk$set(message = FALSE, warning = FALSE,dev="cairo_pdf") ``` \newpage # Summary statistics Basic summary statistics ```{r} data("pembrolizumab") rm_covsum(data=pembrolizumab, covs=c('age','sex')) ``` Set `IQR = T` for interquartile range instead of Min/Max ```{r} rm_covsum(data=pembrolizumab, covs=c('age','sex'),IQR=TRUE) ``` Or `all.stats=T` for both ```{r} rm_covsum(data=pembrolizumab, covs=c('age','sex'),all.stats = TRUE) ``` \newpage This will produce summary statistics by Sex ```{r} rm_covsum(data=pembrolizumab, maincov = 'sex', covs=c('age','pdl1','change_ctdna_group')) ``` To indicate which statistical test was used use `show.tests=TRUE` ```{r} rm_covsum(data=pembrolizumab, maincov = 'sex', covs=c('age','pdl1','change_ctdna_group'), show.tests=TRUE) ``` \newpage Effect sizes can be added with `effSize = TRUE`. Effect size measures include the Wilcoxon r for Wilcoxon rank-sum test, Cohen's d for t-test, Eta squared for Kruskal Wallis test and ANOVA, and Cramer's V for categorical variables. ```{r} rm_covsum(data=pembrolizumab, maincov = 'sex', covs=c('age','pdl1','change_ctdna_group'), show.tests=TRUE, effSize=TRUE) ``` \newpage Group comparisons are non-parametric by default, specify `testcont='ANOVA'` for t-tests/ANOVA ```{r} rm_covsum(data=pembrolizumab, maincov = 'sex', covs=c('age','pdl1'), testcont='ANOVA', show.tests=TRUE, effSize=TRUE) ``` \newpage The default is to indicate percentages by columns (ie percentages within columns add to 100) ```{r} rm_covsum(data=pembrolizumab, maincov = 'sex', covs=c('cohort'), pvalue = FALSE) ``` But you can also specify to show by row instead ```{r} rm_covsum(data=pembrolizumab, maincov = 'sex', covs=c('cohort'), pvalue = FALSE, percentage='row') ``` \newpage # Univariate regression Combining multiple univariate regression analyses into a single table ```{r } rm_uvsum(data=pembrolizumab, response='orr', covs=c('age','pdl1','change_ctdna_group'),p.adjust = 'holm') ``` If the response is continuous linear regression is the default ```{r } rm_uvsum(data=pembrolizumab, response='l_size', covs=c('age','cohort')) ``` ...unless two variables are specified and then survival analysis is run ```{r } rm_uvsum(data=pembrolizumab, response=c('os_time','os_status'), covs=c('age','pdl1','change_ctdna_group')) ``` \newpage Correlated observations can be handled using GEE ```{r} data("ctDNA") rm_uvsum(response = 'size_change', covs=c('time','ctdna_status'), gee=TRUE, id='id', corstr="exchangeable", family=gaussian("identity"), data=ctDNA,showN=TRUE) ``` If you want to check the underlying models, set `returnModels = TRUE` ```{r} rm_uvsum(response = 'orr', covs=c('age','sex'), data=pembrolizumab,returnModels = TRUE) ``` \newpage # Multivariable analysis To create a nice display for multivariable models the model needs to first be fit. By default, the variance inflation factor will be shown to check for multicollinearity. To suppress this column set `vif=FALSE`. Note: variance inflation factors are not computed (yet) for multilevel or GEE models. ```{r} glm_fit <- glm(orr~change_ctdna_group+pdl1+age, family='binomial', data = pembrolizumab) rm_mvsum(glm_fit,p.adjust = 'holm') ``` p-values can be adjusted for multiple comparisons using any of the options available in the `p.adjust` function. This argument is also available for univariate models run with rm_uvsum. ```{r} rm_mvsum(glm_fit, showN = TRUE, vif=TRUE,p.adjust = 'holm') ``` \newpage # Combining univariate and multivariable models To display both models in a single table run the rm_uvsum and rm_mvsum functions with `tableOnly=TRUE` and combine. ```{r} uvsumTable <- rm_uvsum(data=pembrolizumab, response='orr', covs=c('age','sex','pdl1','change_ctdna_group'),tableOnly = TRUE) glm_fit <- glm(orr~change_ctdna_group+pdl1, family='binomial', data = pembrolizumab) mvsumTable <- rm_mvsum(glm_fit, showN = TRUE,tableOnly = TRUE) rm_uv_mv(uvsumTable,mvsumTable) ``` \newpage This can also be done with adjusted p-values, but when combined the raw p-values are dropped ```{r} uvsumTable <- rm_uvsum(data=pembrolizumab, response='orr', covs=c('age','sex','pdl1','change_ctdna_group'),tableOnly = TRUE,p.adjust='holm') glm_fit <- glm(orr~change_ctdna_group+pdl1, family='binomial', data = pembrolizumab) mvsumTable <- rm_mvsum(glm_fit,tableOnly = TRUE,p.adjust='holm') rm_uv_mv(uvsumTable,mvsumTable) ``` \newpage # Changing the output If you need to make changes to the tables, setting `tableOnly=TRUE` will return a data frame for any of the `rm_` functions. Changes can be made, and the table output using `outTable()` ```{r} mvsumTable <- rm_mvsum(glm_fit, showN = TRUE,tableOnly = TRUE) names(mvsumTable)[1] <-'Predictor' outTable(mvsumTable) ``` # Combining tables Tables can be nested with the `nestTable()` function ```{r} cohortA <- rm_uvsum(data=subset(pembrolizumab,cohort=='A'), response = 'pdl1', covs=c('age','sex'), tableOnly = T) cohortA$Cohort <- 'Cohort A' cohortE <- rm_uvsum(data=subset(pembrolizumab,cohort=='E'), response = 'pdl1', covs=c('age','sex'), tableOnly = T) cohortE$Cohort <- 'Cohort E' nestTable(rbind(cohortA,cohortE),head_col = 'Cohort',to_col = 'Covariate') ``` \newpage # Simple Survival Summaries Displaying survival probabilities at different times by sex using Kaplan Meier estimates ```{r} rm_survsum(data=pembrolizumab,time='os_time',status='os_status', group="sex",survtimes=seq(12,36,12),survtimeunit='months') ``` \newpage # Survival Times in Long Format Displaying survival probabilities at different times by sex using Cox PH estimates ```{r} rm_survtime(data=pembrolizumab,time='os_time',status='os_status', strata="sex",survtimes=c(12,24),survtimeunit='mo',type='PH') ``` Displaying survival probabilities at different times by sex, adjusting for age using Cox PH estimates ```{r} rm_survtime(data=pembrolizumab,time='os_time',status='os_status', covs='age', strata="sex",survtimes=c(12,24),survtimeunit='mo',type='PH') ``` \newpage # Stratified Survival Summary ```{r} rm_survdiff(data=pembrolizumab,time='os_time',status='os_status', covs='sex',strata='cohort',digits=1) ``` \newpage # Working with Labels Variable labels will be shown in the `nicenames` argument is set to `TRUE` (the default). Variable labels are set using the `label` attribute of individual variables (assigned using `reportRmd` or another package like `haven`). `reportRmd` supports the addition, removal and export of labels using the following functions: - `set_labels` will set labels for a data frame from a lookup table - `set_var_labels` allows you to set individual variable labels to a data frame - `clear_labels` removes all labels from a data frame - `export_labels` extracts variable labels from a data frame and returns a data frame of variable names and variable labels ## Worked Example Get some descriptive stats for the ctDNA data that comes with the package. The `nicenames` argument is TRUE by default so underscores are replaced by spaces ```{r} data(ctDNA) rm_covsum(data=ctDNA, covs=c('cohort','ctdna_status','size_change')) ``` ### set_labels {#sec-set_labels} If we have a lookup table of variable names and labels that we imported from a data dictionary we can set the variable labels for the data frame and these will be used in the `rm_` functions ```{r} ctDNA_names <- data.frame(var=names(ctDNA), label=c('Patient ID', 'Study Cohort', 'Change in ctDNA since baseline', 'Number of weeks on treatment', 'Percentage change in tumour measurement')) ctDNA <- set_labels(ctDNA,ctDNA_names) rm_covsum(data=ctDNA, covs=c('cohort','ctdna_status','size_change')) ``` ### set_var_labels {#sec-set_var_labels} Individual labels can be changed with with the `set_var_labels` command ```{r} ctDNA <- set_var_labels(ctDNA, cohort="A new cohort label") rm_covsum(data=ctDNA, covs=c('cohort','ctdna_status','size_change')) ``` ### extract_labels {#sec-extract_labels} Extract the variable labels to a data frame ```{r} var_labels <- extract_labels(ctDNA) var_labels ``` ### clear_labels {#sec-clear_labels} Or clear them all ```{r} ctDNA <- clear_labels(ctDNA) ``` \newpage # Plotting Functions ## Plotting bivariate relationships These plots are designed for quick inspection of many variables, not for publication. This is the plotting version of rm_uvsum ```{r, , fig.width=7, fig.height=4} plotuv(data=pembrolizumab, response='orr', covs=c('age','cohort','pdl1','change_ctdna_group')) ``` \newpage ## Plotting univariable odds ratios This will default to linear scale, but can be set to log scale using `logScale=TRUE` ```{r, , fig.width=7, fig.height=2} forestplotUV(data=pembrolizumab, response='orr', covs=c('age','sex','pdl1','change_ctdna_group')) ``` \newpage ## Plotting multivariable odds ratios ```{r, , fig.width=7, fig.height=2} require(ggplot2) glm_fit <- glm(orr~change_ctdna_group+pdl1, family='binomial', data = pembrolizumab) forestplotMV(glm_fit) ``` \newpage # Plotting combined univariable and multivariable model odd ratios To display odds ratios from univariate and multivariable models in a single forest plot, run the forestplotUV and forestplotMV functions and combine. ```{r} uvFP <- forestplotUV(data=pembrolizumab, response='orr', covs=c('age','sex','pdl1','change_ctdna_group')) glm_fit <- glm(orr~change_ctdna_group+pdl1, family='binomial', data = pembrolizumab) mvFP <- forestplotMV(glm_fit) forestplotUVMV(uvFP,mvFP,showN=T,showEvent=T) ``` \newpage This can also be done with log scale odds ratios (default is linear scale). Number of subjects and/or number of events can also be turned off, as well as different colours used. ```{r} uvFP <- forestplotUV(data=pembrolizumab, response='orr', covs=c('age','sex','pdl1','change_ctdna_group')) glm_fit <- glm(orr~change_ctdna_group+pdl1, family='binomial', data = pembrolizumab) mvFP <- forestplotMV(glm_fit) forestplotUVMV(uvFP,mvFP,showN=F,showEvent=F,colours=c("orange","black","blue"),logScale=T) ``` \newpage ## Plotting survival curves ```{r, fig.width=7,fig.height=5} ggkmcif(response = c('os_time','os_status'), cov='cohort', data=pembrolizumab) ``` \newpage # Options The following options can be set: - reportRmd.digits, detault is 2. Sets the default number of digits in output functions. Does not affect p-values. - reportRmd.forceWald, default is FALSE. If set to TRUE then Wald CI, as opposed to likelihood profile CI will be used in the rm_uvsum function. - reportRmd.logScale, default is TRUE. The scale of the forest plots will default to log unless otherwise specified. Example: ```{r} rm_uvsum(response = 'baseline_ctdna', covs=c('age','sex','l_size','pdl1','tmb'), data=pembrolizumab) options('reportRmd.digits'=1) rm_uvsum(response = 'baseline_ctdna', covs=c('age','sex','l_size','pdl1','tmb'), data=pembrolizumab) ``` \newpage # PDF Output For pdf to be correctly generate when using survival curves it is recommended that the cairo format be used. This can be specified with the following command in the setup code chunk: `knitr::opts_chunk$set(message = FALSE, warning = FALSE,dev="cairo_pdf")` # Data Sets ## pembrolizumab Survival status and ctDNA levels for patients receiving pembrolizumab A data frame with 94 rows and 15 variables: - **id** Patient ID - **age** Age at study entry - **sex** Patient Sex - **cohort** Study Cohort: A = Squamous cell carcinoma of soft pallate, B = Triple negative breast cancer, C = Ovarian, high grade serous, D = Melanoma, E = Other Solid Tumor - **l_size** Target lesion size at baseline - **pdl1** PD L1 percent - **tmb** log of TMB - **baseline_ctdna** Baseline ctDNA - **change_ctdna_group** Did ctDNA increase or decrease from baseline to cycle 3 - **orr** Objective Response - **cbr** Clinical Beneficial Response - **os_status** Overall survival status, 0 = alive, 1 = deceased - **os_time** Overall survival time in months - **pfs_status** Progression free survival status, 0 = progression free, 1 = progressed - **pfs_time** Progression free survival time in months ## ctDNA Longitudinal changes in tumour size since baseline for patients by changes in ctDNA status (clearance, decrease or increase) since baseline. A data frame with 270 rows and 5 variables: - **id** Patient ID - **cohort** Study Cohort: A = Squamous cell carcinoma of soft pallate, B = Triple negative breast cancer, C = Ovarian, high grade serous, D = Melanoma, E = Other Solid Tumor - **ctdna_status** Change in ctDNA since baseline - **time** Number of weeks on treatment - **size_change** Percentage change in tumour measurement - **increase** dichotomous variable indicating if size_change is negative/0 or positive