diff --git a/R/post.R b/R/post.R index cfc5ec4..52a02b3 100644 --- a/R/post.R +++ b/R/post.R @@ -50,6 +50,13 @@ #' @importFrom dplyr pull #' @importFrom purrr safely map map2 #' @importFrom distributional dist_normal dist_mixture is_distribution parameters +#' @examples +#' library(distributional) +#' library(dplyr) +#' post_treated <- calc_post_norm(internal_data = filter(int_norm_df, trt == 1), +#' response = y, +#' prior = dist_normal(50, 10), +#' internal_sd = 0.15) #' calc_post_norm<- function( internal_data, @@ -150,12 +157,13 @@ calc_post_norm<- function( #' @importFrom dplyr pull #' @importFrom purrr safely map map2 #' @importFrom distributional dist_beta dist_mixture is_distribution parameters -#' -calc_post_beta<- function( - internal_data, - response, - prior -){ +#' @examples +#' library(dplyr) +#' library(distributional) +#' calc_post_beta(internal_data = filter(int_binary_df, trt == 1), +#' response = y, +#' prior = dist_beta(0.5, 0.5)) +calc_post_beta<- function(internal_data, response, prior){ # Checking internal data and response variable if(is_prop_scr(internal_data)){ data <- internal_data$internal_df diff --git a/R/ps.R b/R/ps.R index fd3b34b..0cf36ee 100644 --- a/R/ps.R +++ b/R/ps.R @@ -48,6 +48,20 @@ #' @importFrom dplyr mutate filter tibble as_tibble #' @importFrom stats glm #' @importFrom cobalt bal.tab +#' @examples +#' # This can be used for both continuous and binary data +#' library(dplyr) +#' # Continuous +#' calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), +#' external_df = ex_norm_df, +#' id_col = subjid, +#' model = ~ cov1 + cov2 + cov3 + cov4) +#' # Binary +#' calc_prop_scr(internal_df = filter(int_binary_df, trt == 0), +#' external_df = ex_binary_df, +#' id_col = subjid, +#' model = ~ cov1 + cov2 + cov3 + cov4) +#' calc_prop_scr <- function(internal_df, external_df, id_col, model, ...){ if(!is_formula(model)){ @@ -197,6 +211,14 @@ glance.prop_scr <- function(x, ...){ #' #' @return Boolean #' @export +#' @examples +#' library(dplyr) +#' x <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), +#' external_df = ex_norm_df, +#' id_col = subjid, +#' model = ~ cov1 + cov2 + cov3 + cov4) +#' is_prop_scr(x) +#' is_prop_scr <- function(x){ inherits(x, "prop_scr") } @@ -237,6 +259,16 @@ test_prop_scr <- function(x){ #' theme_bw #' @importFrom dplyr bind_rows #' @importFrom stringr str_glue +#' @examples +#' library(dplyr) +#' ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), +#' external_df = ex_norm_df, +#' id_col = subjid, +#' model = ~ cov1 + cov2 + cov3 + cov4) +#' # Plotting the Propensity Scores +#' prop_scr_hist(ps_obj) +#' # Or plotting the inverse probability weights +#' prop_scr_hist(ps_obj, variable = "ipw") prop_scr_hist <- function(x, variable = c("propensity score", "ps", "inverse probability weight", "ipw"), ...){ test_prop_scr(x) @@ -293,6 +325,17 @@ prop_scr_hist <- function(x, variable = c("propensity score", "ps", "inverse pro #' theme_bw #' @importFrom dplyr bind_rows #' @importFrom stringr str_glue +#' @examples +#' library(dplyr) +#' ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), +#' external_df = ex_norm_df, +#' id_col = subjid, +#' model = ~ cov1 + cov2 + cov3 + cov4) +#' # Plotting the Propensity Scores +#' prop_scr_dens(ps_obj) +#' # Or plotting the inverse probability weights +#' prop_scr_dens(ps_obj, variable = "ipw") +#' prop_scr_dens <- function(x, variable = c("propensity score", "ps", "inverse probability weight", "ipw"), ...){ test_prop_scr(x) @@ -348,6 +391,15 @@ prop_scr_dens <- function(x, variable = c("propensity score", "ps", "inverse pro #' @importFrom ggplot2 ggplot aes geom_point labs scale_color_manual ggtitle #' theme_bw geom_vline #' @importFrom tidyr pivot_longer +#' @examples +#' library(dplyr) +#' ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), +#' external_df = ex_norm_df, +#' id_col = subjid, +#' model = ~ cov1 + cov2 + cov3 + cov4) +#' # Plotting the Propensity Scores +#' prop_scr_love(ps_obj, reference_line = 0.1) +#' prop_scr_love <- function(x, reference_line = NULL, ...){ test_prop_scr(x) diff --git a/R/utils.R b/R/utils.R index aee1272..11061b8 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,6 +1,8 @@ #' Plot Distribution #' -#' @param ... Distributional object(s) to plot. If there are multiple objects you can name them. +#' @param ... Distributional object(s) to plot. When passing multiple objects +#' naming them will change the labels in the plot, else they will use the +#' distributional format #' #' @return ggplot object that is the density of the provided distribution #' @export @@ -9,6 +11,12 @@ #' @importFrom ggplot2 ggplot theme_bw #' @importFrom ggdist stat_slabinterval #' @importFrom purrr map_chr map_lgl +#' @examples +#' library(distributional) +#' plot_dist(dist_normal(0, 1)) +#' #Plotting Multiple +#' plot_dist(dist_normal(0, 1), dist_normal(10, 5)) +#' plot_dist('Prior' = dist_normal(0, 1), 'Posterior' = dist_normal(10, 5)) plot_dist <- function(...){ input <- list(...) if(!all(map_lgl(input, is_distribution))){ @@ -20,7 +28,7 @@ plot_dist <- function(...){ fill_alpha <- ifelse(n > 1, 0.5, 1) if(is.null(Distributions) & n > 1){ Distributions <- map_chr(input, format) - if(unique(Distributions) != n) + if(length(unique(Distributions)) != n) Distributions <- paste0(1:n,": ", Distributions) } diff --git a/README.Rmd b/README.Rmd index ce06184..ad3e92a 100644 --- a/README.Rmd +++ b/README.Rmd @@ -2,7 +2,6 @@ output: github_document --- - ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, @@ -13,114 +12,36 @@ knitr::opts_chunk$set( ``` # beastt -## Bayesian Evaluation, Analysis, and Simulation Software Tools for Trials (BEASTT) + +## Bayesian Evaluation, Analysis, and Simulation Software Tools for Trials (beastt) -[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) -[![CRAN status](https://www.r-pkg.org/badges/version/beastt)](https://CRAN.R-project.org/package=beastt) -[![R-CMD-check](https://github.com/GSK-Biostatistics/beastt/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/GSK-Biostatistics/beastt/actions/workflows/R-CMD-check.yaml) + +[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) [![CRAN status](https://www.r-pkg.org/badges/version/beastt)](https://CRAN.R-project.org/package=beastt) [![R-CMD-check](https://github.com/GSK-Biostatistics/beastt/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/GSK-Biostatistics/beastt/actions/workflows/R-CMD-check.yaml) + ## Overview -Welcome to the "beastt" package! This R package is designed to assist users in performing -Bayesian dynamic borrowing with covariate adjustment via inverse probability weighting for -simulations and data analyses in clinical trials. +Welcome to the "beastt" package! This R package is designed to assist users in performing Bayesian dynamic borrowing with covariate adjustment via inverse probability weighting for simulations and data analyses in clinical trials. ## Installation -You can install the development version of beastt from [GitHub](https://github.com/) with: +You can install the development version of {beastt} from [GitHub](https://github.com/) with: ``` r # install.packages("devtools") devtools::install_github("GSK-Biostatistics/beastt") ``` -## Functions - -### `calc_prop_scr()` - -Calculate propensity scores using this function and obtain the inverse probability weight -calculated for each subject. Propensity scores are essential in order to balance baseline -covariate distributions between internal and external trial participants. - -**Usage:** - -```R -calc_prop_scr(internal_df, external_df, id_col, model) -``` - -- `internal_df`: Internal dataset. -- `external_df`: External dataset. -- `id_col`: Name of the column in both datasets used to identify each subject. -- `model`: Model used to calculate propensity scores. - -### `calc_power_prior()` - -Calculate power priors based on a distribution, hyperparameters, a weighted object and a response variable. -Power priors provide a Bayesian framework for incorporating external information into the analysis. - -**Usage:** - -```R -calc_power_prior(prior, weighted_obj, response) -``` - -- `prior`: A {distributional} object that is the prior of the external data. -- `weighted_obj`: A weighted object created by calling `calc_prop_scr()`. -- `response`: Name of the response variable. -- `...`: Additional parameters needed depending on the type of power prior used. - -## Examples - -Here are some examples demonstrating the usage of the package: - -```R -library(beastt) -library(ggdist) -library(ggplot2) - -set.seed(1234) +## Usage -# Create internal and external datasets -internal_df <- data.frame(id_col = 1:20, cov1 = rnorm(10, 2), cov2 = rnorm(100, 20), - y = rnorm(20, mean = 5, sd = 3) -external_df <- data.frame(id_col = 21:40, cov1 = rnorm(10, 2), cov2 = rnorm(100, 18), - y = rnorm(20, mean = 8, sd = 4) - -# Example for propensity score calculation -model <- as.formula("~cov1 + cov2") -psscores <- calc_prop_scr(internal_df = internal_df, external_df = external_df, - id_col = id_col, model = model) - -# Example for power prior calculation using a Normal prior for external data -powerprior <- calc_power_prior(prior = dist_normal(15, 100), weighted_obj = psscores, - response = y) - -# Plot power prior and interval -ggplot(tibble(), aes(xdist = powerprior, y = 1)) + - stat_slabinterval() -``` +At the moment {beastt} covers cases when borrowing from external control data with either normal or binary endpoints. For more information, see the vignettes. Future updates are expected to include cases with survival endpoints and repeated measure. ## Contributing -Feel free to contribute to the "beastt" package by reporting issues or submitting pull requests on the GitHub repository. +Feel free to contribute to the {beastt} package by reporting issues or submitting pull requests on the GitHub repository. ## License -This package is released under the [Apache License](>= 2). - - - - - - - - - - - - - - - +This package is released under the [Apache License](%3E=%202). diff --git a/README.md b/README.md index 9976429..63fdba9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # beastt -## Bayesian Evaluation, Analysis, and Simulation Software Tools for Trials (BEASTT) +## Bayesian Evaluation, Analysis, and Simulation Software Tools for Trials (beastt) @@ -10,17 +10,19 @@ experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](h [![CRAN status](https://www.r-pkg.org/badges/version/beastt)](https://CRAN.R-project.org/package=beastt) [![R-CMD-check](https://github.com/GSK-Biostatistics/beastt/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/GSK-Biostatistics/beastt/actions/workflows/R-CMD-check.yaml) + ## Overview Welcome to the “beastt” package! This R package is designed to assist -users in performing Bayesian Dynamic Borrowing with covariate adjustment -for simulations and data analyses in clinical trials. +users in performing Bayesian dynamic borrowing with covariate adjustment +via inverse probability weighting for simulations and data analyses in +clinical trials. ## Installation -You can install the development version of beastt from +You can install the development version of {beastt} from [GitHub](https://github.com/) with: ``` r @@ -28,81 +30,15 @@ You can install the development version of beastt from devtools::install_github("GSK-Biostatistics/beastt") ``` -## Functions - -### `calc_prop_scr()` - -Calculate propensity scores using this function and obtain the inverse -probability weight calculated for each subject. Propensity scores are -essential in order to balance covariates between internal and external -trial participants. - -**Usage:** - -``` r -calc_prop_scr(internal_df, external_df, id_col, model) -``` - -- `internal_df`: Internal dataset. -- `external_df`: External dataset. -- `id_col`: Name of the column in both datasets used to identify each - subject. -- `model`: Model used to calculate propensity scores. - -### `calc_power_prior()` - -Calculate power priors based on a distribution, hyperparameters, a -weighted object and a response variable. Power priors provide a Bayesian -framework for incorporating external information into the analysis. +## Usage -**Usage:** - -``` r -calc_power_prior(prior, weighted_obj, response) -``` - -- `prior`: a {distributional} object that is the prior of the external - data. -- `weighted_obj`: A weighted object created by calling - `calc_prop_scr()`. -- `response`: Name of the response variable. -- `...`: Additional parameters needed depending on the type of power - prior used. - -## Examples - -Here are some examples demonstrating the usage of the package: - -``` r -library(beastt) -library(ggdist) -library(ggplot2) - -set.seed(1234) - -# Create internal and external datasets -internal_df <- data.frame(id_col = 1:20, cov1 = rnorm(10, 2), cov2 = rnorm(100, 20), - y = rnorm(20, mean = 5, sd = 3) -external_df <- data.frame(id_col = 21:40, cov1 = rnorm(10, 2), cov2 = rnorm(100, 18), - y = rnorm(20, mean = 8, sd = 4) - -# Example for propensity score calculation -model <- as.formula("~cov1 + cov2") -psscores <- calc_prop_scr(internal_df = internal_df, external_df = external_df, - id_col = id_col, model = model) - -# Example for power prior calculation using a Normal prior for external data -powerprior <- calc_power_prior(prior = dist_normal(15, 100), weighted_obj = psscores, - response = y) - -# Plot power prior and interval -ggplot(tibble(), aes(xdist = powerprior, y = 1)) + - stat_slabinterval() -``` +At the moment {beastt} covers cases when borrowing from external control data with either normal or binary endpoints. +For more information, see the vignettes. Future updates are expected to include cases +with survival endpoints and repeated measure. ## Contributing -Feel free to contribute to the “beastt” package by reporting issues or +Feel free to contribute to the {beastt} package by reporting issues or submitting pull requests on the GitHub repository. ## License diff --git a/man/calc_post_beta.Rd b/man/calc_post_beta.Rd index 5d4ab39..760b799 100644 --- a/man/calc_post_beta.Rd +++ b/man/calc_post_beta.Rd @@ -40,3 +40,10 @@ distribution for \eqn{\theta} is either a beta distribution or a mixture of beta components depending on whether the prior is a single beta distribution or a mixture distribution. } +\examples{ +library(dplyr) +library(distributional) +calc_post_beta(internal_data = filter(int_binary_df, trt == 1), + response = y, + prior = dist_beta(0.5, 0.5)) +} diff --git a/man/calc_post_norm.Rd b/man/calc_post_norm.Rd index 07b91d2..865504c 100644 --- a/man/calc_post_norm.Rd +++ b/man/calc_post_norm.Rd @@ -60,3 +60,12 @@ is a normal distribution. If \code{internal_sd = NULL} or if other types of prio distributions are specified (e.g., mixture or t distribution), then the posterior distribution is a mixture of normal distributions. } +\examples{ +library(distributional) +library(dplyr) +post_treated <- calc_post_norm(internal_data = filter(int_norm_df, trt == 1), + response = y, + prior = dist_normal(50, 10), + internal_sd = 0.25) + +} diff --git a/man/calc_prop_scr.Rd b/man/calc_prop_scr.Rd index 7991399..6b6362a 100644 --- a/man/calc_prop_scr.Rd +++ b/man/calc_prop_scr.Rd @@ -54,3 +54,18 @@ In a weighted estimator, data from participants in the external study are given a weight of \eqn{\hat{e}(x_i)⁄(1 - \hat{e}(x_i))} whereas data from participants in the internal trial are given a weight of 1. } +\examples{ +# This can be used for both continuous and binary data +library(dplyr) +# Continuous +calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), + external_df = ex_norm_df, + id_col = subjid, + model = ~ cov1 + cov2 + cov3 + cov4) +# Binary +calc_prop_scr(internal_df = filter(int_binary_df, trt == 0), + external_df = ex_binary_df, + id_col = subjid, + model = ~ cov1 + cov2 + cov3 + cov4) + +} diff --git a/man/is_prop_scr.Rd b/man/is_prop_scr.Rd index e77968f..eea48fe 100644 --- a/man/is_prop_scr.Rd +++ b/man/is_prop_scr.Rd @@ -15,3 +15,12 @@ Boolean \description{ Test If Propensity Score Object } +\examples{ +library(dplyr) +x <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), + external_df = ex_norm_df, + id_col = subjid, + model = ~ cov1 + cov2 + cov3 + cov4) +is_prop_scr(x) + +} diff --git a/man/plot_dist.Rd b/man/plot_dist.Rd index 5fb72b1..5c7e037 100644 --- a/man/plot_dist.Rd +++ b/man/plot_dist.Rd @@ -7,7 +7,9 @@ plot_dist(...) } \arguments{ -\item{...}{Distributional object(s) to plot. If there are multiple objects you can name them.} +\item{...}{Distributional object(s) to plot. When passing multiple objects +naming them will change the labels in the plot, else they will use the +distributional format} } \value{ ggplot object that is the density of the provided distribution @@ -15,3 +17,10 @@ ggplot object that is the density of the provided distribution \description{ Plot Distribution } +\examples{ +library(distributional) +plot_dist(dist_normal(0, 1)) +#Plotting Multiple +plot_dist(dist_normal(0, 1), dist_normal(10, 5)) +plot_dist('Prior' = dist_normal(0, 1), 'Posterior' = dist_normal(10, 5)) +} diff --git a/man/prop_scr_dens.Rd b/man/prop_scr_dens.Rd index 6d1b8d9..645b7aa 100644 --- a/man/prop_scr_dens.Rd +++ b/man/prop_scr_dens.Rd @@ -26,3 +26,15 @@ ggplot object Plot overlapping density curves of the propensity scores for both the internal and external participants, or plot external IPWs. } +\examples{ +library(dplyr) +ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), + external_df = ex_norm_df, + id_col = subjid, + model = ~ cov1 + cov2 + cov3 + cov4) +# Plotting the Propensity Scores +prop_scr_dens(ps_obj) +# Or plotting the inverse probability weights +prop_scr_dens(ps_obj, variable = "ipw") + +} diff --git a/man/prop_scr_hist.Rd b/man/prop_scr_hist.Rd index 45456f1..8de7a84 100644 --- a/man/prop_scr_hist.Rd +++ b/man/prop_scr_hist.Rd @@ -26,3 +26,14 @@ ggplot object Plot overlapping histograms of the propensity scores for both the internal and external participants, or plot external IPWs. } +\examples{ +library(dplyr) +ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), + external_df = ex_norm_df, + id_col = subjid, + model = ~ cov1 + cov2 + cov3 + cov4) +# Plotting the Propensity Scores +prop_scr_hist(ps_obj) +# Or plotting the inverse probability weights +prop_scr_hist(ps_obj, variable = "ipw") +} diff --git a/man/prop_scr_love.Rd b/man/prop_scr_love.Rd index e986cfa..94f215e 100644 --- a/man/prop_scr_love.Rd +++ b/man/prop_scr_love.Rd @@ -21,3 +21,13 @@ ggplot object Plot the unadjusted and IPW-adjusted absolute standardized mean differences for each covariate. } +\examples{ +library(dplyr) +ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), + external_df = ex_norm_df, + id_col = subjid, + model = ~ cov1 + cov2 + cov3 + cov4) +# Plotting the Propensity Scores +prop_scr_love(ps_obj, reference_line = 0.1) + +} diff --git a/man/robustify_norm.Rd b/man/robustify_norm.Rd index 9951a74..b73eb68 100644 --- a/man/robustify_norm.Rd +++ b/man/robustify_norm.Rd @@ -21,6 +21,16 @@ mixture distribution Adds vague normal component, where the level of vagueness is controlled by the \code{n} parameter } +\details{ +In cases with a normal endpoint, a robust mixture prior can be created by +adding a vague normal component to any normal prior with mean \eqn{\theta} +and variance \eqn{\sigma^2}.The vague component is calculated to have the +same mean \eqn{\theta} and variance equal to \eqn{\sigma^2 \times n}, where +\code{n} is the specified number of theoretical participants. If robustifying a normal +power prior that was calculated from external control data and \code{n} is defined as +the number of external control participants, and the vague component would +then correspond to one external control participant's worth of data. +} \examples{ library(distributional) robustify_norm(dist_normal(0,1), n = 15) diff --git a/vignettes/introduction.Rmd b/vignettes/introduction.Rmd deleted file mode 100644 index 4c5cb76..0000000 --- a/vignettes/introduction.Rmd +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Package Introduction" -package: beastt -output: - rmarkdown::html_vignette: - toc: true -vignette: > - %\VignetteIndexEntry{Package Introduction} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - - -```{r, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -library(beastt) -``` - -In this vignette, you will learn about the scope of `beastt()` and where to find additional information on how to implement your analysis in `beastt()`. - -## Introduction - -Bayesian dynamic borrowing (BDB) is a way to incorporate external data into the analysis of data from an internal trial to effectively increase the sample size and in turn increase power. BEASTT focuses on implementing BDB, specifically through the use of inverse probability weighted power priors that can be incorporated into a robust mixtures prior. - -`beastt` has the following goals: - -- goal 1 -- goal 2 -- goal 3 - - -## Common Usage - -### Create Data Sets - -```{r eval=FALSE} -library(beastt) -library(ggdist) -library(ggplot2) - -set.seed(1234) - -# Create internal and external datasets -internal_df <- data.frame(id_col = 1:20, cov1 = rnorm(10, 2), cov2 = rnorm(100, 20), - y = rnorm(20, mean = 5, sd = 3) -external_df <- data.frame(id_col = 21:40, cov1 = rnorm(10, 2), cov2 = rnorm(100, 18), - y = rnorm(20, mean = 8, sd = 4) - -``` - - -### Propensity Score - - -### Power Prior