diff --git a/R/mod_tableGen_fct_methods.R b/R/mod_tableGen_fct_methods.R index 8f5dddcd..65577026 100644 --- a/R/mod_tableGen_fct_methods.R +++ b/R/mod_tableGen_fct_methods.R @@ -72,6 +72,8 @@ app_methods <- function(agg, column, week, group, data, totals, filter = NA) { app_freq(column, group, data, totals) } else if (agg == "ANOVA") { app_anova(column, week, group, data) + } else if (agg == "RM_ANOVA") { + app_rmanova(column, week, group, data) } else if (agg == "NESTED_FREQ_DSC"){ app_nested_freq(column, week, group, data, totals, sort = "desc_tot") } else if (agg == "NESTED_FREQ_ABC"){ diff --git a/R/mod_tableGen_fct_rmanova.R b/R/mod_tableGen_fct_rmanova.R new file mode 100644 index 00000000..a86e7e75 --- /dev/null +++ b/R/mod_tableGen_fct_rmanova.R @@ -0,0 +1,168 @@ +#' Generate RM-ANOVA using table generator blocks +#' +#' @param column the variable to perform RM-ANOVA on, +#' this also contains the class of the column +#' based on the data file the column came from +#' @param week filter the variable by certain week +#' @param group the groups to compare for the RM-ANOVA +#' @param data the data to use +#' +#' @return an RM-ANOVA table of grouped variables +#' @family tableGen Functions +#' @keywords tabGen +#' +#' @noRd +app_rmanova <- function(column, week, group, data) { + UseMethod("app_rmanova", column) +} + + +#' @return NULL +#' @rdname app_rmanova +#' @family tableGen Functions +#' @noRd + +app_rmanova.default <- function(column, week, group, data) { + rlang::abort(glue::glue( + "Can't calculate mean because data is not classified as ADLB, BDS or OCCDS", + )) +} + +#' if ADSL supplied look for the column to take mean of +#' and look for a grouping variable to group_by +#' +#' @importFrom rlang sym !! +#' @import dplyr +#' @return an RM-ANOVA table of grouped variables +#' @rdname app_rmanova +#' @family tableGen Functions +#' +#' @noRd + +app_rmanova.ADAE <- app_rmanova.ADSL <- function(column, week, group = NULL, data) { + + column <- as.character(column) + + if (!is.numeric(data[[column]])) { + stop(paste("Can't calculate RM-ANOVA, ", column, " is not numeric")) + } + + if (is.null(group)) { + + stop(paste("Can't calculate RM-ANOVA without grouping data")) + + } else { + group <- rlang::sym(group) + column <- rlang::sym(column) + + all_dat <- data %>% dplyr::distinct(!!column, !!group, USUBJID) + + ttest <- summary(aov(all_dat[[paste(column)]] ~ all_dat[[paste(group)]] + Error(factor(USUBJID)), data=all_dat))[[1]][[1]] %>% + tidyr::as_tibble() + + group_n <- length(unique(all_dat[[paste(group)]])) + 2 + + anova_df <- data.frame(matrix(NA, ncol=group_n, nrow=4)) + + anova_df[1,1] <- "p-value" + anova_df[2,1] <- "Test Statistic" + anova_df[3,1] <- "Mean Sum of Squares" + anova_df[4,1] <- "Sum of Squares" + anova_df[1, group_n] <- round(ttest$`Pr(>F)`[1], 3) + anova_df[2, group_n] <- round(ttest$`F value`[1], 2) + anova_df[3, group_n] <- round(ttest$`Mean Sq`[1], 2) + anova_df[4, group_n] <- round(ttest$`Sum Sq`[1], 2) + + anova_df <- dplyr::mutate_all(anova_df, as.character) %>% + dplyr::mutate_all(dplyr::coalesce, "") + + anova_df + } + + +} + + +#' if BDS filter by paramcd and week +#' We need to calculate the difference in N for this +#' and report missing values from the mean if any +#' +#' @importFrom rlang sym !! +#' @import dplyr +#' @return an ANOVA table of grouped variables +#' @rdname app_rmanova +#' @family tableGen Functions +#' +#' @noRd + +app_rmanova.BDS <- function(column, week, group = NULL, data) { + + column <- as.character(column) + + if (!column %in% data[["PARAMCD"]]) { + stop(paste("Can't calculate RM-ANOVA, ", column, " has no AVAL")) + } + + if (week == "NONE") { + stop(paste("Select week from dropdown to calculate RM-ANOVA")) + } + + + if (is.null(group)) { + stop(paste("Can't calculate RM-ANOVA without grouping data")) + } else { + group <- sym(group) + + all_dat <- data %>% filter(PARAMCD == column & AVISIT == week) + + if (length(unique(all_dat[[paste(group)]])) == 1) stop(glue::glue("Only one {group} in data selected, choose another week for RM-ANOVA")) + + ttest <- summary(aov(all_dat$AVAL ~ all_dat[[paste(group)]] + Error(factor(USUBJID)), data=all_dat))[[1]][[1]] %>% + tidyr::as_tibble() + + group_n <- length(unique(all_dat[[paste(group)]])) + 2 + + anova_df <- data.frame(matrix(NA, ncol=group_n, nrow=4)) + anova_df[1,1] <- "p-value" + anova_df[2,1] <- "Test Statistic" + anova_df[3,1] <- "Mean Sum of Squares" + anova_df[4,1] <- "Sum of Squares" + anova_df[1, group_n] <- round(ttest$`Pr(>F)`[1], 3) + anova_df[2, group_n] <- round(ttest$`F value`[1], 2) + anova_df[3, group_n] <- round(ttest$`Mean Sq`[1], 2) + anova_df[4, group_n] <- round(ttest$`Sum Sq`[1], 2) + + anova_df <- dplyr::mutate_all(anova_df, as.character) %>% + dplyr::mutate_all(dplyr::coalesce, "") + anova_df + } + +} + +#' @return NULL +#' @rdname app_rmanova +#' @family tableGen Functions +#' +#' @noRd + +app_rmanova.OCCDS <- function(column, week = NULL, group = NULL, data) { + rlang::abort(glue::glue( + "Currently no method to perform RM-ANOVA on OCCDS" + )) +} + + + + + +#' @return NULL +#' @rdname app_rmanova +#' @family tableGen Functions +#' +#' @noRd + +app_rmanova.custom <- function(column, week = NULL, group = NULL, data) { + rlang::abort(glue::glue( + "Can't calculate RM-ANOVA, data is not classified as ADLB, BDS or OCCDS" + )) +} diff --git a/R/mod_tableGen_ui.R b/R/mod_tableGen_ui.R index ffd13a97..008155a5 100644 --- a/R/mod_tableGen_ui.R +++ b/R/mod_tableGen_ui.R @@ -77,6 +77,10 @@ mod_tableGen_ui <- function(id){ class = "ui-state-default agg", id = "anova", div(tippy(div("ANOVA"), "ANOVA")) ), + tags$li( + class = "ui-state-default agg", id = "rm_anova", + div(tippy(div("RM-ANOVA"), "Repeated Measures ANOVA")) + ), tags$li( class = "ui-state-default agg", id = "chg", div(tippy(div("CHG"), "Change from Baseline")) diff --git a/R/sysdata.rda b/R/sysdata.rda index 34771ede..accc6e75 100644 Binary files a/R/sysdata.rda and b/R/sysdata.rda differ diff --git a/data-raw/internal-data.R b/data-raw/internal-data.R index ff2efab0..4498a3d3 100644 --- a/data-raw/internal-data.R +++ b/data-raw/internal-data.R @@ -1,7 +1,8 @@ pretty_blocks <- tidyr::tibble( - Pattern = c("MEAN", "FREQ", "CHG", "Y_FREQ", "MAX_FREQ", "NON_MISSING", + Pattern = c("RM_ANOVA", "MEAN", "FREQ", "CHG", "Y_FREQ", "MAX_FREQ", "NON_MISSING", "NESTED_FREQ_DSC", "NESTED_FREQ_ABC"), - Replacement = c("Descriptive Statistics", + Replacement = c("Repeated Measures ANOVA", + "Descriptive Statistics", "Summary Counts", "Descriptive Statistics of Change from Baseline", "Subject Count for those with 'Y' values", diff --git a/inst/app/www/js/script.js b/inst/app/www/js/script.js index 7a9ff7e3..1da5ad61 100644 --- a/inst/app/www/js/script.js +++ b/inst/app/www/js/script.js @@ -167,8 +167,10 @@ $(function() { var draggableId = ui.draggable.attr("id"); var newid = getNewId(draggableId); if (weeks_array) { - if (draggableId.includes("anova")) { + if (draggableId === "anova") { $(this).append(selectBlock(newid, "ANOVA", week_opts)); + } else if (draggableId === "rm_anova") { + $(this).append(selectBlock(newid, "RM_ANOVA", week_opts)); } else if (draggableId.includes("chg")) { $(this).append(selectBlock(newid, "CHG", week_opts)); } else if (draggableId.includes("mean")) {