From 33627abc07551b3284779d874fd082b7899db206 Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Wed, 3 Dec 2025 11:21:47 -0500 Subject: [PATCH 1/3] adding lintr and air --- Syndemics/.lintr | 31 +++++ Syndemics/R/buildLifeTables.R | 168 +++++++++++++--------- Syndemics/R/compare_moud.R | 128 +++++++++-------- Syndemics/R/compare_oud.R | 132 ++++++++++-------- Syndemics/R/crc.R | 163 ++++++++++++---------- Syndemics/R/fetch_sas.R | 38 +++-- Syndemics/R/internal_crcTools.R | 168 +++++++++++++--------- Syndemics/R/loadOutputFiles.R | 35 +++-- Syndemics/R/residential_admissions.R | 63 +++++---- Syndemics/R/respond_inputManipulations.R | 170 ++++++++++++++--------- Syndemics/air.toml | 11 ++ 11 files changed, 661 insertions(+), 446 deletions(-) create mode 100644 Syndemics/.lintr create mode 100644 Syndemics/air.toml diff --git a/Syndemics/.lintr b/Syndemics/.lintr new file mode 100644 index 0000000..36a9512 --- /dev/null +++ b/Syndemics/.lintr @@ -0,0 +1,31 @@ +linters: all_linters( + assignment_linter = assignment_linter(operator = c("<-"), allow_trailing = FALSE), + backport_linter = backport_linter("4.0.0"), + brace_linter = brace_linter(allow_single_line = TRUE), + indentation_linter = indentation_linter(indent = 4L), + line_length_linter = line_length_linter(length = 80L), + object_name_linter = object_name_linter(styles = c("snake_case", "lowercase", "SNAKE_CASE")), + return_linter = return_linter(return_style = "explicit", allow_implicit_else = FALSE), + cyclocomp_linter = cyclocomp_linter(complexity_limit = 10L), + pipe_consistency_linter = pipe_consistency_linter("auto"), + unused_import_linter = unused_import_linter(interpret_glue = TRUE), + undesirable_function_linter = undesirable_function_linter( + fun = modify_defaults( + defaults = default_undesirable_functions, + source = NULL, + library = NULL, + require = NULL)), + object_usage_linter = NULL, # This doesn't work well with dplyr + condition_call_linter = NULL, + condition_message_linter = NULL, + consecutive_mutate_linter = NULL, + expect_identical_linter = NULL, + implicit_integer_linter = NULL, + library_call_linter = NULL, + literal_coercion_linter = NULL, + print_linter = NULL, # This one is the opposite of our style guide + sample_int_linter = NULL, # I disagree with this one in terms of clarity + strings_as_factors_linter = NULL, # Not relevant given > R 4.0.0 + unnecessary_placeholder_linter = NULL # I disagree with the style + ) +exclusions: list() diff --git a/Syndemics/R/buildLifeTables.R b/Syndemics/R/buildLifeTables.R index cd801d1..a0c5397 100644 --- a/Syndemics/R/buildLifeTables.R +++ b/Syndemics/R/buildLifeTables.R @@ -14,21 +14,31 @@ #' @importFrom utils write.csv #' @export -build_background_mortality_file <- function(files, - outputfile, - races = c("black", "hispanic", "white"), - sexes = c("female", "male"), - age_groups = c("1_20", "21_40", "41_60", "61_80", "81_100"), - bin_size = 20) { - - background_mortality <- lapply(files, extract_background_mortality, - bin_size = bin_size, age_groups = age_groups) - result_table <- create_and_fill_table(background_mortality, races, sexes, age_groups) - if (!missing(outputfile)) { - write.csv(result_table, outputfile, row.names = FALSE) - } - - return(result_table) +build_background_mortality_file <- function( + files, + outputfile, + races = c("black", "hispanic", "white"), + sexes = c("female", "male"), + age_groups = c("1_20", "21_40", "41_60", "61_80", "81_100"), + bin_size = 20 +) { + background_mortality <- lapply( + files, + extract_background_mortality, + bin_size = bin_size, + age_groups = age_groups + ) + result_table <- create_and_fill_table( + background_mortality, + races, + sexes, + age_groups + ) + if (!missing(outputfile)) { + write.csv(result_table, outputfile, row.names = FALSE) + } + + return(result_table) } #' Function used to extract background mortality values based on age from a single yearly CDC NVSS life table @@ -41,33 +51,48 @@ build_background_mortality_file <- function(files, #' @importFrom readxl read_excel #' @keywords internal -extract_background_mortality <- function(file_path, bin_size = 20, age_groups = c("1_20", "21_40", "41_60", "61_80", "81_100")) { - data <- readxl::read_excel(file_path, skip = 1) - dt <- as.data.table(data)[(2:101)] - - # Rename columns to standard names - setnames(dt, "Probability of dying between ages x and x + 1", "year_prob", skip_absent = TRUE) - setnames(dt, "Number dying between ages x and x + 1", "year_deaths", skip_absent = TRUE) - - #Data table bindings - year_prob <- year_deaths <- V1 <- NULL - - dt[, year_prob := as.numeric(year_prob) - ][, year_deaths := as.numeric(year_deaths)] - - bin_groups <- (seq(nrow(dt)) - 1) %/% bin_size - deaths_by_group <- dt[, sum(year_deaths), by = bin_groups][, V1] - - # 100k originates from the CDC NVSS data - reported in rates per 100,000 persons - weekly_rates <- (deaths_by_group / 100000) / 52 - weekly_probs <- 1 - exp(-weekly_rates) - - result <- data.table( - agegrp = age_groups, - weekly_probability = weekly_probs - ) - - return(result) +extract_background_mortality <- function( + file_path, + bin_size = 20, + age_groups = c("1_20", "21_40", "41_60", "61_80", "81_100") +) { + data <- readxl::read_excel(file_path, skip = 1) + dt <- as.data.table(data)[(2:101)] + + # Rename columns to standard names + setnames( + dt, + "Probability of dying between ages x and x + 1", + "year_prob", + skip_absent = TRUE + ) + setnames( + dt, + "Number dying between ages x and x + 1", + "year_deaths", + skip_absent = TRUE + ) + + #Data table bindings + year_prob <- year_deaths <- V1 <- NULL + + dt[, year_prob := as.numeric(year_prob)][, + year_deaths := as.numeric(year_deaths) + ] + + bin_groups <- (seq(nrow(dt)) - 1) %/% bin_size + deaths_by_group <- dt[, sum(year_deaths), by = bin_groups][, V1] + + # 100k originates from the CDC NVSS data - reported in rates per 100,000 persons + weekly_rates <- (deaths_by_group / 100000) / 52 + weekly_probs <- 1 - exp(-weekly_rates) + + result <- data.table( + agegrp = age_groups, + weekly_probability = weekly_probs + ) + + return(result) } #' Create and fill the table with mortality values for all demographic combinations @@ -80,29 +105,38 @@ extract_background_mortality <- function(file_path, bin_size = 20, age_groups = #' @import data.table #' @keywords internal -create_and_fill_table <- function(background_mortality, - races = c("black", "hispanic", "white"), - sexes = c("female", "male"), - age_groups = c("1_20", "21_40", "41_60", "61_80", "81_100")) { - #Data table bindings - agegrp <- NULL - - combinations <- expand.grid(races = races, sexes = sexes, stringsAsFactors = FALSE) - combinations <- as.data.table(combinations) - result_table <- combinations[rep(seq_len(nrow(combinations)), each = length(age_groups))] - result_table[, agegrp := rep(age_groups, times = nrow(combinations))] - n_race_sex_combos <- length(races) * length(sexes) - - mortality_data <- data.table() - for (i in seq_along(background_mortality)) { - group_index <- ((i - 1) %% n_race_sex_combos) + 1 - bg_mort <- background_mortality[[i]] - demo_info <- combinations[group_index] - mortality_group <- cbind(demo_info[rep(1, nrow(bg_mort))], bg_mort) - mortality_data <- rbind(mortality_data, mortality_group) - } - - setorder(mortality_data, races, sexes, agegrp) - - return(mortality_data) +create_and_fill_table <- function( + background_mortality, + races = c("black", "hispanic", "white"), + sexes = c("female", "male"), + age_groups = c("1_20", "21_40", "41_60", "61_80", "81_100") +) { + #Data table bindings + agegrp <- NULL + + combinations <- expand.grid( + races = races, + sexes = sexes, + stringsAsFactors = FALSE + ) + combinations <- as.data.table(combinations) + result_table <- combinations[rep( + seq_len(nrow(combinations)), + each = length(age_groups) + )] + result_table[, agegrp := rep(age_groups, times = nrow(combinations))] + n_race_sex_combos <- length(races) * length(sexes) + + mortality_data <- data.table() + for (i in seq_along(background_mortality)) { + group_index <- ((i - 1) %% n_race_sex_combos) + 1 + bg_mort <- background_mortality[[i]] + demo_info <- combinations[group_index] + mortality_group <- cbind(demo_info[rep(1, nrow(bg_mort))], bg_mort) + mortality_data <- rbind(mortality_data, mortality_group) + } + + setorder(mortality_data, races, sexes, agegrp) + + return(mortality_data) } diff --git a/Syndemics/R/compare_moud.R b/Syndemics/R/compare_moud.R index a634512..472fa20 100644 --- a/Syndemics/R/compare_moud.R +++ b/Syndemics/R/compare_moud.R @@ -23,71 +23,87 @@ #' @export compare_moud <- function(old_path, new_path) { - N_ID <- treatment <- new_count <- old_count <- difference <- NULL + N_ID <- treatment <- new_count <- old_count <- difference <- NULL - # read and label the datasets - old <- read.csv(old_path, stringsAsFactors = FALSE) - new <- read.csv(new_path, stringsAsFactors = FALSE) + # read and label the datasets + old <- read.csv(old_path, stringsAsFactors = FALSE) + new <- read.csv(new_path, stringsAsFactors = FALSE) - old_df <- old %>% - dplyr::mutate(version = "Old") - new_df <- new %>% - dplyr::mutate(version = "New") + old_df <- old %>% + dplyr::mutate(version = "Old") + new_df <- new %>% + dplyr::mutate(version = "New") - # combine datasets and add date - combined <- dplyr::bind_rows(old_df, new_df) %>% - dplyr::mutate(date = as.Date(paste(year, month, "01", sep = "-"))) + # combine datasets and add date + combined <- dplyr::bind_rows(old_df, new_df) %>% + dplyr::mutate(date = as.Date(paste(year, month, "01", sep = "-"))) - - # plot 1: time series of MOUD counts by treatment - count_plot <- ggplot2::ggplot(combined, ggplot2::aes(x = date, y = N_ID, color = version, linetype = version)) + - ggplot2::geom_line(linewidth = 1) + - ggplot2::facet_wrap(~ treatment, scales = "free_y") + - ggplot2::labs( - title = "Monthly MOUD Counts by Treatment Type: Old vs New Dataset", - x = "Date", - y = "MOUD Count", - color = "Version", - linetype = "Version" + # plot 1: time series of MOUD counts by treatment + count_plot <- ggplot2::ggplot( + combined, + ggplot2::aes(x = date, y = N_ID, color = version, linetype = version) ) + - ggplot2::scale_color_manual(values = c("Old" = "grey", "New" = "purple")) + - ggplot2::theme_minimal() + - ggplot2::theme( - legend.position = "top", - axis.text.x = ggplot2::element_text(angle = 45, hjust = 1) - ) - - # prepare difference dataset - old_df2 <- old %>% - dplyr::select(treatment, month, year, N_ID) %>% - dplyr::rename(old_count = N_ID) + ggplot2::geom_line(linewidth = 1) + + ggplot2::facet_wrap(~treatment, scales = "free_y") + + ggplot2::labs( + title = "Monthly MOUD Counts by Treatment Type: Old vs New Dataset", + x = "Date", + y = "MOUD Count", + color = "Version", + linetype = "Version" + ) + + ggplot2::scale_color_manual( + values = c("Old" = "grey", "New" = "purple") + ) + + ggplot2::theme_minimal() + + ggplot2::theme( + legend.position = "top", + axis.text.x = ggplot2::element_text(angle = 45, hjust = 1) + ) - new_df2 <- new %>% - dplyr::select(treatment, month, year, N_ID) %>% - dplyr::rename(new_count = N_ID) + # prepare difference dataset + old_df2 <- old %>% + dplyr::select(treatment, month, year, N_ID) %>% + dplyr::rename(old_count = N_ID) - diff_df <- dplyr::left_join(old_df2, new_df2, by = c("treatment", "month", "year")) %>% - dplyr::mutate( - difference = new_count - old_count, - date = as.Date(paste(year, month, "01", sep = "-")) - ) + new_df2 <- new %>% + dplyr::select(treatment, month, year, N_ID) %>% + dplyr::rename(new_count = N_ID) + diff_df <- dplyr::left_join( + old_df2, + new_df2, + by = c("treatment", "month", "year") + ) %>% + dplyr::mutate( + difference = new_count - old_count, + date = as.Date(paste(year, month, "01", sep = "-")) + ) - # plot 2: difference in MOUD counts - difference_plot <- ggplot2::ggplot(diff_df, ggplot2::aes(x = date, y = difference, fill = difference > 0)) + - ggplot2::geom_col(show.legend = FALSE) + - ggplot2::facet_wrap(~ treatment, scales = "free_y") + - ggplot2::scale_fill_manual(values = c("TRUE" = "darkgreen", "FALSE" = "firebrick")) + - ggplot2::geom_hline(yintercept = 0, linetype = "dashed") + - ggplot2::labs( - title = "Change in MOUD Counts by Treatment Type: New vs Old", - x = "Date", - y = "Difference in MOUD Count (New vs Old)" + # plot 2: difference in MOUD counts + difference_plot <- ggplot2::ggplot( + diff_df, + ggplot2::aes(x = date, y = difference, fill = difference > 0) ) + - ggplot2::theme_minimal() + - ggplot2::theme( - axis.text.x = ggplot2::element_text(angle = 45, hjust = 1) - ) + ggplot2::geom_col(show.legend = FALSE) + + ggplot2::facet_wrap(~treatment, scales = "free_y") + + ggplot2::scale_fill_manual( + values = c("TRUE" = "darkgreen", "FALSE" = "firebrick") + ) + + ggplot2::geom_hline(yintercept = 0, linetype = "dashed") + + ggplot2::labs( + title = "Change in MOUD Counts by Treatment Type: New vs Old", + x = "Date", + y = "Difference in MOUD Count (New vs Old)" + ) + + ggplot2::theme_minimal() + + ggplot2::theme( + axis.text.x = ggplot2::element_text(angle = 45, hjust = 1) + ) - return(list(count_plot = count_plot, difference_plot = difference_plot, difference_data = diff_df)) + return(list( + count_plot = count_plot, + difference_plot = difference_plot, + difference_data = diff_df + )) } diff --git a/Syndemics/R/compare_oud.R b/Syndemics/R/compare_oud.R index fd47db0..2072837 100644 --- a/Syndemics/R/compare_oud.R +++ b/Syndemics/R/compare_oud.R @@ -11,16 +11,16 @@ #' @importFrom data.table fread rbindlist #' @export combine_files <- function(path) { - source_file <- NULL - files <- list.files(path, full.names = TRUE) - rbindlist( - lapply(files, function(f) { - d <- fread(f) - d[, source_file := basename(f)] - d - }), - fill = TRUE - ) + source_file <- NULL + files <- list.files(path, full.names = TRUE) + rbindlist( + lapply(files, function(f) { + d <- fread(f) + d[, source_file := basename(f)] + d + }), + fill = TRUE + ) } #' Plot OUD Counts Over Time @@ -36,22 +36,27 @@ combine_files <- function(path) { #' @importFrom scales label_comma #' @export time_trends <- function(data) { - N_ID <- source_file <- total <- NULL - yearly_totals <- data[, list(total = sum(N_ID, na.rm = TRUE)), by = c(year, source_file)] + N_ID <- source_file <- total <- NULL + yearly_totals <- data[, + list(total = sum(N_ID, na.rm = TRUE)), + by = c(year, source_file) + ] - p <- ggplot(yearly_totals, aes(x = year, y = total, color = source_file)) + - geom_line(size = 1) + - geom_point(size = 2) + - labs(title = "OUD Counts Over Time", - x = "Year", - y = "Total Count", - color = "Data Source") + - scale_y_continuous(labels = scales::label_comma()) + - theme_minimal() + - theme(legend.position = "bottom") + p <- ggplot(yearly_totals, aes(x = year, y = total, color = source_file)) + + geom_line(size = 1) + + geom_point(size = 2) + + labs( + title = "OUD Counts Over Time", + x = "Year", + y = "Total Count", + color = "Data Source" + ) + + scale_y_continuous(labels = scales::label_comma()) + + theme_minimal() + + theme(legend.position = "bottom") - print(p) - return(p) + print(p) + return(p) } #' Compare Annual OUD Counts Across Files @@ -66,26 +71,33 @@ time_trends <- function(data) { #' @importFrom data.table dcast #' @export compare_by_year <- function(data) { - N_ID <- total <- source_file <- NULL - yearly_totals <- data[, list(total = sum(N_ID, na.rm = TRUE)), by = c(year, source_file)] - comparison_table <- dcast(yearly_totals, year ~ source_file, value.var = "total") - print(comparison_table) - return(comparison_table) + N_ID <- total <- source_file <- NULL + yearly_totals <- data[, + list(total = sum(N_ID, na.rm = TRUE)), + by = c(year, source_file) + ] + comparison_table <- dcast( + yearly_totals, + year ~ source_file, + value.var = "total" + ) + print(comparison_table) + return(comparison_table) } #' Filter OUD Data by Source File Pattern #' #' Extracts rows from the dataset where the source_file column matches a specified pattern. #' #' @param data A \code{data.table} containing a \code{source_file} column. -#' @param pattern A character string containing a regular expression pattern to match +#' @param pattern A character string containing a regular expression pattern to match #' against the \code{source_file} column. #' @param ignore_case Logical; if TRUE, pattern matching is case-insensitive. Default is TRUE. #' #' @return A filtered \code{data.table} containing only rows where source_file matches the pattern. #' @export get_filtered_data <- function(data, pattern, ignore_case = TRUE) { - source_file <- NULL - return(data[grepl(pattern, source_file, ignore.case = ignore_case)]) + source_file <- NULL + return(data[grepl(pattern, source_file, ignore.case = ignore_case)]) } #' Plot OUD Counts by Demographic Category @@ -104,23 +116,23 @@ get_filtered_data <- function(data, pattern, ignore_case = TRUE) { #' @importFrom scales label_comma #' @export plot_oud_data <- function(data, group_col, labels, title, legend_title) { - N_ID <- total <- group_name <- NULL - totals <- data[, list(total = sum(N_ID, na.rm = TRUE)), by = c("year", group_col)] - totals$group_name <- labels[as.character(totals[[group_col]])] - - p <- ggplot(totals, aes(x = year, y = total, color = group_name)) + - geom_line(size = 1) + - geom_point(size = 2) + - labs(title = title, - x = "Year", - y = "Count", - color = legend_title) + - scale_y_continuous(labels = scales::label_comma()) + - theme_minimal() + - theme(legend.position = "bottom") - - print(p) - return(p) + N_ID <- total <- group_name <- NULL + totals <- data[, + list(total = sum(N_ID, na.rm = TRUE)), + by = c("year", group_col) + ] + totals$group_name <- labels[as.character(totals[[group_col]])] + + p <- ggplot(totals, aes(x = year, y = total, color = group_name)) + + geom_line(size = 1) + + geom_point(size = 2) + + labs(title = title, x = "Year", y = "Count", color = legend_title) + + scale_y_continuous(labels = scales::label_comma()) + + theme_minimal() + + theme(legend.position = "bottom") + + print(p) + return(p) } #' Histogram of OUD Counts @@ -135,15 +147,17 @@ plot_oud_data <- function(data, group_col, labels, title, legend_title) { #' @importFrom scales label_comma #' @export histogram <- function(data) { - N_ID <- NULL - p <- ggplot(data, aes(x = N_ID)) + - geom_histogram(bins = 30, fill = "lightblue", color = "black") + - labs(title = "Distribution of OUD Counts", - x = "Count", - y = "Frequency") + - scale_y_continuous(labels = scales::label_comma()) + - theme_minimal() + N_ID <- NULL + p <- ggplot(data, aes(x = N_ID)) + + geom_histogram(bins = 30, fill = "lightblue", color = "black") + + labs( + title = "Distribution of OUD Counts", + x = "Count", + y = "Frequency" + ) + + scale_y_continuous(labels = scales::label_comma()) + + theme_minimal() - print(p) - return(p) + print(p) + return(p) } diff --git a/Syndemics/R/crc.R b/Syndemics/R/crc.R index 540a706..1291eea 100644 --- a/Syndemics/R/crc.R +++ b/Syndemics/R/crc.R @@ -17,87 +17,108 @@ #' @importFrom stats AIC coef confint formula glm poisson #' @export -crc <- function(data, freq.column, binary.variables, method = "poisson", formula.selection = "stepwise", formula = NULL, - opts.stepwise = list( - direction = "both", - threshold = 0.05, - verbose = TRUE - )) { - if (!(method %in% c("poisson", "negbin"))) { - stop("Method must be either 'poisson' or 'negbin'") - } - - if (!(formula.selection %in% c("aic", "stepwise"))) { - stop("Formula selection must be either 'aic' or 'stepwise'") - } - - dt <- setDT(data) +crc <- function( + data, + freq.column, + binary.variables, + method = "poisson", + formula.selection = "stepwise", + formula = NULL, + opts.stepwise = list( + direction = "both", + threshold = 0.05, + verbose = TRUE + ) +) { + if (!(method %in% c("poisson", "negbin"))) { + stop("Method must be either 'poisson' or 'negbin'") + } - if (is.null(formula)) { - if (formula.selection == "aic") { - form <- formula_list(freq.column, binary.variables) - } else if (formula.selection == "stepwise") { - form <- NULL + if (!(formula.selection %in% c("aic", "stepwise"))) { + stop("Formula selection must be either 'aic' or 'stepwise'") } - } else if (!is.formula(formula)) { - stop("Expected Formula Object when Specifying Formula") - } else { - form <- formula - } - if (formula.selection == "aic") { - results <- list() + dt <- setDT(data) - for (i in seq_along(form)) { - result <- tryCatch({ - if (method == "poisson") { - model <- stats::glm(form[[i]], data = dt, family = "poisson") - } else { - model <- MASS::glm.nb(formula = form[[i]], data = dt) + if (is.null(formula)) { + if (formula.selection == "aic") { + form <- formula_list(freq.column, binary.variables) + } else if (formula.selection == "stepwise") { + form <- NULL } + } else if (!is.formula(formula)) { + stop("Expected Formula Object when Specifying Formula") + } else { + form <- formula + } - intercept <- exp(stats::coef(model)["(Intercept)"]) - aic <- stats::AIC(model) + if (formula.selection == "aic") { + results <- list() - ci <- suppressMessages(stats::confint(model, "(Intercept)", level = 0.95)) - lower_ci <- exp(ci[1]) - upper_ci <- exp(ci[2]) + for (i in seq_along(form)) { + result <- tryCatch( + { + if (method == "poisson") { + model <- stats::glm( + form[[i]], + data = dt, + family = "poisson" + ) + } else { + model <- MASS::glm.nb(formula = form[[i]], data = dt) + } - data.frame( - formula = paste(deparse(form[[i]]), collapse = " "), - estimate = round(intercept, 2), - AIC = round(aic, 2), - lower_ci = unname(round(lower_ci, 2)), - upper_ci = unname(round(upper_ci, 2)), - error = NA, - row.names = NULL - ) - }, error = function(e) { - data.frame( - formula = paste(deparse(form[[i]]), collapse = " "), - estimate = NA, - AIC = NA, - lower_ci = NA, - upper_ci = NA, - error = toString(e$message), - row.names = NULL - ) - }) + intercept <- exp(stats::coef(model)["(Intercept)"]) + aic <- stats::AIC(model) - results[[i]] <- result - } + ci <- suppressMessages(stats::confint( + model, + "(Intercept)", + level = 0.95 + )) + lower_ci <- exp(ci[1]) + upper_ci <- exp(ci[2]) - model <- do.call(rbind, results) - model <- model[order(model$AIC), ] + data.frame( + formula = paste(deparse(form[[i]]), collapse = " "), + estimate = round(intercept, 2), + AIC = round(aic, 2), + lower_ci = unname(round(lower_ci, 2)), + upper_ci = unname(round(upper_ci, 2)), + error = NA, + row.names = NULL + ) + }, + error = function(e) { + data.frame( + formula = paste(deparse(form[[i]]), collapse = " "), + estimate = NA, + AIC = NA, + lower_ci = NA, + upper_ci = NA, + error = toString(e$message), + row.names = NULL + ) + } + ) + + results[[i]] <- result + } - } else if (formula.selection == "stepwise") { - model <- step_regression(data, freq.column, binary.variables, - p.threshold = opts.stepwise$threshold, - direction = opts.stepwise$direction, - method = method, - verbose = opts.stepwise$verbose, - k = 2) - } + model <- do.call(rbind, results) + model <- model[order(model$AIC), ] + } else if (formula.selection == "stepwise") { + model <- step_regression( + data, + freq.column, + binary.variables, + p.threshold = opts.stepwise$threshold, + direction = opts.stepwise$direction, + method = method, + verbose = opts.stepwise$verbose, + k = 2 + ) + } - return(model) + return(model) } diff --git a/Syndemics/R/fetch_sas.R b/Syndemics/R/fetch_sas.R index f7d725f..abbeec3 100644 --- a/Syndemics/R/fetch_sas.R +++ b/Syndemics/R/fetch_sas.R @@ -4,17 +4,33 @@ #' @importFrom httr GET stop_for_status content config #' #' @export -fetch_sas <- function(){ - if(!dir.exists("SAS")) dir.create("SAS") - req <- httr::GET("https://api.github.com/repos/SyndemicsLab/PHD/git/trees/main?recursive=1") - httr::stop_for_status(req) +fetch_sas <- function() { + if (!dir.exists("SAS")) { + dir.create("SAS") + } + req <- httr::GET( + "https://api.github.com/repos/SyndemicsLab/PHD/git/trees/main?recursive=1" + ) + httr::stop_for_status(req) - file_list <- grep(".sas", unlist(lapply(httr::content(req)$tree, "[", "path"), use.names = FALSE), - value = TRUE, fixed = TRUE) + file_list <- grep( + ".sas", + unlist(lapply(httr::content(req)$tree, "[", "path"), use.names = FALSE), + value = TRUE, + fixed = TRUE + ) - for(i in seq_along(file_list)){ - response <- httr::GET(paste0("https://raw.githubusercontent.com/SyndemicsLab/PHD/main/", file_list[i]), - config = config(ssl_verifypeer = FALSE)) - writeBin(content(response, "raw"), paste0("SAS/", gsub(".*/", "", file_list[i]))) - } + for (i in seq_along(file_list)) { + response <- httr::GET( + paste0( + "https://raw.githubusercontent.com/SyndemicsLab/PHD/main/", + file_list[i] + ), + config = config(ssl_verifypeer = FALSE) + ) + writeBin( + content(response, "raw"), + paste0("SAS/", gsub(".*/", "", file_list[i])) + ) + } } diff --git a/Syndemics/R/internal_crcTools.R b/Syndemics/R/internal_crcTools.R index b7df361..ed4567f 100644 --- a/Syndemics/R/internal_crcTools.R +++ b/Syndemics/R/internal_crcTools.R @@ -5,8 +5,8 @@ #' #' @export -is.formula <- function(x){ - inherits(x, "formula") +is.formula <- function(x) { + inherits(x, "formula") } #' Generates All Possible Combination of Interaction Terms @@ -20,33 +20,45 @@ is.formula <- function(x){ #' @export formula_list <- function(y, x) { - n <- length(x) - all_formulas <- list() - - for (i in 1:n) { - all_formulas <- c(all_formulas, paste0(y, "~", x[i])) - } - - for (i in 2:n) { - combinations <- combn(x, i) - for (j in 1:ncol(combinations)) { - combination <- combinations[,j] - - all_formulas <- c(all_formulas, paste0(y, "~", paste(combination, collapse="+"))) - interaction_formula <- paste(combination, collapse="*") - all_formulas <- c(all_formulas, paste0(y, "~", interaction_formula)) - - for (k in 1:(i-1)) { - combinations_additive <- combn(combination, k) - for (l in 1:ncol(combinations_additive)) { - combination_additive <- combinations_additive[,l] - all_formulas <- c(all_formulas, paste0(y, "~", paste(combination_additive, collapse="+"), "+", interaction_formula)) + n <- length(x) + all_formulas <- list() + + for (i in 1:n) { + all_formulas <- c(all_formulas, paste0(y, "~", x[i])) + } + + for (i in 2:n) { + combinations <- combn(x, i) + for (j in 1:ncol(combinations)) { + combination <- combinations[, j] + + all_formulas <- c( + all_formulas, + paste0(y, "~", paste(combination, collapse = "+")) + ) + interaction_formula <- paste(combination, collapse = "*") + all_formulas <- c(all_formulas, paste0(y, "~", interaction_formula)) + + for (k in 1:(i - 1)) { + combinations_additive <- combn(combination, k) + for (l in 1:ncol(combinations_additive)) { + combination_additive <- combinations_additive[, l] + all_formulas <- c( + all_formulas, + paste0( + y, + "~", + paste(combination_additive, collapse = "+"), + "+", + interaction_formula + ) + ) + } + } } - } } - } - return(lapply(unique(all_formulas), as.formula)) + return(lapply(unique(all_formulas), as.formula)) } #' Helper function for stepwise regression @@ -64,50 +76,68 @@ formula_list <- function(y, x) { #' @importFrom utils capture.output #' @importFrom stats AIC coef confint formula glm poisson step -step_regression <- function(data, y, x, method = "poisson", direction = "both", - p.threshold = 0.05, k = 2, verbose = TRUE) { - formula_init <- as.formula(paste(y, "~", paste(x, collapse = " + "))) - formula_max <- as.formula(paste(y, "~ (", paste(x, collapse = " + "), ")^", k)) - - if (!verbose) { - capture.output({ - if (method == "poisson") { - init_mod <- glm(formula_init, family = poisson, data = data) - } else { - init_mod <- MASS::glm.nb(formula_init, data = data) - } - - final_mod <- suppressWarnings(step(init_mod, - scope = list(upper = formula_max, lower = formula_init), - direction = direction, - k = log(nrow(data)))) - }) - } else { - if (method == "poisson") { - init_mod <- glm(formula_init, family = poisson, data = data) +step_regression <- function( + data, + y, + x, + method = "poisson", + direction = "both", + p.threshold = 0.05, + k = 2, + verbose = TRUE +) { + formula_init <- as.formula(paste(y, "~", paste(x, collapse = " + "))) + formula_max <- as.formula(paste( + y, + "~ (", + paste(x, collapse = " + "), + ")^", + k + )) + + if (!verbose) { + capture.output({ + if (method == "poisson") { + init_mod <- glm(formula_init, family = poisson, data = data) + } else { + init_mod <- MASS::glm.nb(formula_init, data = data) + } + + final_mod <- suppressWarnings(step( + init_mod, + scope = list(upper = formula_max, lower = formula_init), + direction = direction, + k = log(nrow(data)) + )) + }) } else { - init_mod <- MASS::glm.nb(formula_init, data = data) + if (method == "poisson") { + init_mod <- glm(formula_init, family = poisson, data = data) + } else { + init_mod <- MASS::glm.nb(formula_init, data = data) + } + + final_mod <- step( + init_mod, + scope = list(upper = formula_max, lower = formula_init), + direction = direction, + k = log(nrow(data)) + ) } - final_mod <- step(init_mod, - scope = list(upper = formula_max, lower = formula_init), - direction = direction, - k = log(nrow(data))) - } - - intercept <- coef(final_mod)[1] - estimate <- exp(intercept) - ci <- exp(confint(final_mod)[1, ]) - - results <- list( - model = method, - formula = formula(final_mod), - summary = summary(final_mod), - estimate = unname(round(estimate, 2)), - lower_ci = unname(round(ci[1], 2)), - upper_ci = unname(round(ci[2], 2)), - AIC = AIC(final_mod) - ) - - return(results) + intercept <- coef(final_mod)[1] + estimate <- exp(intercept) + ci <- exp(confint(final_mod)[1, ]) + + results <- list( + model = method, + formula = formula(final_mod), + summary = summary(final_mod), + estimate = unname(round(estimate, 2)), + lower_ci = unname(round(ci[1], 2)), + upper_ci = unname(round(ci[2], 2)), + AIC = AIC(final_mod) + ) + + return(results) } diff --git a/Syndemics/R/loadOutputFiles.R b/Syndemics/R/loadOutputFiles.R index a0028d3..33b6529 100644 --- a/Syndemics/R/loadOutputFiles.R +++ b/Syndemics/R/loadOutputFiles.R @@ -24,20 +24,25 @@ #' #' @export loadOutputFiles <- function(N, outputFileNames, pathPrefix = "") { - # append the trailing slash if the prefix does not already - if (pathPrefix != "" && !endsWith(pathPrefix, "/")) { - pathPrefix <- paste0(pathPrefix, "/") - } - outputNumbers <- 1:N - outputTables <- list() - # read files and store them in outputTables - for (index in seq_along(outputNumbers)) { - outputFolder <- paste0("output", index) - currentOutputTables <- list() - for (outputFile in outputFileNames) { - currentOutputTables[[outputFile]] <- read.csv(paste0(pathPrefix, outputFolder, "/", outputFile)) + # append the trailing slash if the prefix does not already + if (pathPrefix != "" && !endsWith(pathPrefix, "/")) { + pathPrefix <- paste0(pathPrefix, "/") } - outputTables[[outputFolder]] <- currentOutputTables - } - return(outputTables) + outputNumbers <- 1:N + outputTables <- list() + # read files and store them in outputTables + for (index in seq_along(outputNumbers)) { + outputFolder <- paste0("output", index) + currentOutputTables <- list() + for (outputFile in outputFileNames) { + currentOutputTables[[outputFile]] <- read.csv(paste0( + pathPrefix, + outputFolder, + "/", + outputFile + )) + } + outputTables[[outputFolder]] <- currentOutputTables + } + return(outputTables) } diff --git a/Syndemics/R/residential_admissions.R b/Syndemics/R/residential_admissions.R index 3e83674..89be6c2 100644 --- a/Syndemics/R/residential_admissions.R +++ b/Syndemics/R/residential_admissions.R @@ -16,42 +16,41 @@ #' print(monthly_avg) #' } process_teds_year <- function(year, data_path) { + # Construct file path and object name + file_name <- paste0("tedsa_puf_", year, "_R.rdata") + full_path <- file.path(data_path, file_name) + object_name <- paste0("TEDSA_PUF_", year) - # Construct file path and object name - file_name <- paste0("tedsa_puf_", year, "_R.rdata") - full_path <- file.path(data_path, file_name) - object_name <- paste0("TEDSA_PUF_", year) + # Load data + load(full_path) - # Load data - load(full_path) + # Convert to tibble + teds <- as_tibble(get(object_name)) - # Convert to tibble - teds <- as_tibble(get(object_name)) + # Filter for Massachusetts + teds <- teds %>% + filter(STFIPS == 25) - # Filter for Massachusetts - teds <- teds %>% - filter(STFIPS == 25) + # Define strata filters (currently commented for customization) + # when GENDER is 2 this represents females, + # when RACE is 5 and ETHNIC is 4 this represents non-Hispanic White individuals, + # when RACE is 4 or 5 and ETHNIC is 1, 2, 3, or 5 this represents Hispanic/Latino individuals that also identify as White or African American/Black, + # when AGE is between 8 - 11 this represents individuals that are 40-64 years old at admission + # when AGE is 12 this represents individuals that are 65 years old or older at admission + # True is a placeholder to ensure code runs if filters are commented out + teds_strat <- teds %>% + filter( + TRUE + ) - # Define strata filters (currently commented for customization) - # when GENDER is 2 this represents females, - # when RACE is 5 and ETHNIC is 4 this represents non-Hispanic White individuals, - # when RACE is 4 or 5 and ETHNIC is 1, 2, 3, or 5 this represents Hispanic/Latino individuals that also identify as White or African American/Black, - # when AGE is between 8 - 11 this represents individuals that are 40-64 years old at admission - # when AGE is 12 this represents individuals that are 65 years old or older at admission - # True is a placeholder to ensure code runs if filters are commented out - teds_strat <- teds %>% - filter( - TRUE - ) + # Final filtering for service type, opioids, and IDU status + teds_final <- teds_strat %>% + filter( + SERVICES %in% c(4, 5), + (SUB1 %in% 5:7 | SUB2 %in% 5:7), + IDU == 1 + ) - # Final filtering for service type, opioids, and IDU status - teds_final <- teds_strat %>% - filter( - SERVICES %in% c(4, 5), - (SUB1 %in% 5:7 | SUB2 %in% 5:7), - IDU == 1 - ) - - # Return monthly admissions number - return(nrow(teds_final) / 12) + # Return monthly admissions number + return(nrow(teds_final) / 12) } diff --git a/Syndemics/R/respond_inputManipulations.R b/Syndemics/R/respond_inputManipulations.R index 1754a35..73f54f7 100644 --- a/Syndemics/R/respond_inputManipulations.R +++ b/Syndemics/R/respond_inputManipulations.R @@ -6,14 +6,25 @@ #' #' @import data.table #' @export -DSA <- function(data, filter, cycle, pct_change){ - data <- as.data.table(data) - initial_block <- NULL - for(c in cycle){ - DT <- data[initial_block == filter, paste0("to_", filter, "_cycle", c) := get(paste0("to_", filter, "_cycle", c))*pct_change - ][, paste0("to_corresponding_post_trt_cycle", c) := 1 - get(paste0("to_", filter, "_cycle", c))] - } - return(DT) +DSA <- function(data, filter, cycle, pct_change) { + data <- as.data.table(data) + initial_block <- NULL + for (c in cycle) { + DT <- data[ + initial_block == filter, + paste0("to_", filter, "_cycle", c) := get(paste0( + "to_", + filter, + "_cycle", + c + )) * + pct_change + ][, + paste0("to_corresponding_post_trt_cycle", c) := 1 - + get(paste0("to_", filter, "_cycle", c)) + ] + } + return(DT) } #' A function to change default age groups from RESPOND shell tables @@ -25,48 +36,71 @@ DSA <- function(data, filter, cycle, pct_change){ #' #' @import data.table #' @export -change_agegrp_chunk <- function(data, size.out, transformation, cols, grouping){ - DT <- as.data.table(data) - agegrp <- age <- NULL - age_min <- age_max <- NULL - if(!cols %in% names(DT)) stop("Column names in 'cols' do not match names in 'data'") - if(missing(grouping)) grouping <- names(DT)[!c(names(DT) %in% c(cols, "agegrp"))] +change_agegrp_chunk <- function( + data, + size.out, + transformation, + cols, + grouping +) { + DT <- as.data.table(data) + agegrp <- age <- NULL + age_min <- age_max <- NULL + if (!cols %in% names(DT)) { + stop("Column names in 'cols' do not match names in 'data'") + } + if (missing(grouping)) { + grouping <- names(DT)[!c(names(DT) %in% c(cols, "agegrp"))] + } - DT <- DT[, `:=` (age_min = as.integer(sub("_(.*)", "", agegrp)), - age_max = as.integer(sub("^(.*?)_", "", agegrp)), - agegrp = NULL)] + DT <- DT[, `:=`( + age_min = as.integer(sub("_(.*)", "", agegrp)), + age_max = as.integer(sub("^(.*?)_", "", agegrp)), + agegrp = NULL + )] - chunk.diffs <- unique(DT[["age_min"]] - DT[["age_max"]]) - if(length(chunk.diffs) > 1){ - stop("Chunk differences non-uniform") - } else size.in <- chunk.diffs*-1 + 1 + chunk.diffs <- unique(DT[["age_min"]] - DT[["age_max"]]) + if (length(chunk.diffs) > 1) { + stop("Chunk differences non-uniform") + } else { + size.in <- chunk.diffs * -1 + 1 + } - # A more efficient method would be to Map(seq, age_min, age_max), - # although unlisting seems to be a problem.... will work on this in the future + # A more efficient method would be to Map(seq, age_min, age_max), + # although unlisting seems to be a problem.... will work on this in the future - expanded <- merge(DT, expand.grid(block = unique(DT[["block"]]), - sex = unique(DT[["sex"]]), - oud = unique(DT[["oud"]]), - age = as.integer(c(min(DT[["age_min"]]):max(DT[["age_max"]])))), - by = grouping, - allow.cartesian = TRUE)[age >= age_min & age <= age_max, - ][, `:=` (age_min = NULL, - age_max = NULL, - agegrp = cut(age, seq(9, 100, size.out), - labels = paste0(seq(10, 98, size.out), - "_", - seq(11, 99, size.out))), - age = NULL) - ] - if(transformation == "sum"){ - out <- expanded[, (cols) := lapply(cols, function(x) get(x)/size.in), - ][, (cols) := lapply(cols, function(x) sum(get(x))), by = c("agegrp", "block", "oud", "sex")] - return(unique(out)) - - } else if(transformation == "mean"){ - out <- expanded[, (cols) := lapply(cols, function(x) mean(x))] - return(unique(out)) - } + expanded <- merge( + DT, + expand.grid( + block = unique(DT[["block"]]), + sex = unique(DT[["sex"]]), + oud = unique(DT[["oud"]]), + age = as.integer(c(min(DT[["age_min"]]):max(DT[["age_max"]]))) + ), + by = grouping, + allow.cartesian = TRUE + )[age >= age_min & age <= age_max, ][, `:=`( + age_min = NULL, + age_max = NULL, + agegrp = cut( + age, + seq(9, 100, size.out), + labels = paste0(seq(10, 98, size.out), "_", seq(11, 99, size.out)) + ), + age = NULL + )] + if (transformation == "sum") { + out <- expanded[, + (cols) := lapply(cols, function(x) get(x) / size.in), + ][, + (cols) := lapply(cols, function(x) sum(get(x))), + by = c("agegrp", "block", "oud", "sex") + ] + return(unique(out)) + } else if (transformation == "mean") { + out <- expanded[, (cols) := lapply(cols, function(x) mean(x))] + return(unique(out)) + } } #' A function to create new blocks for RESPOND (clones 'No_Treatment' blocks and reassigns the name) @@ -76,17 +110,19 @@ change_agegrp_chunk <- function(data, size.out, transformation, cols, grouping){ #' #' @import data.table #' @export -new_block <- function(data, names, column="block"){ - if(!column %in% names(data)) stop(paste(column, "is not in original data")) - data <- as.data.table(data) - data_list <- list() +new_block <- function(data, names, column = "block") { + if (!column %in% names(data)) { + stop(paste(column, "is not in original data")) + } + data <- as.data.table(data) + data_list <- list() - for(n in seq_along(names)){ - DT <- copy(data)[get(column) == "No_Treatment", ] - data_list[[n]] <- DT[, (column) := rep.int(names[n], .N)] - } - out <- data.table::rbindlist(append(data_list, list(data))) - return(out) + for (n in seq_along(names)) { + DT <- copy(data)[get(column) == "No_Treatment", ] + data_list[[n]] <- DT[, (column) := rep.int(names[n], .N)] + } + out <- data.table::rbindlist(append(data_list, list(data))) + return(out) } #' A function to change values to another block; follows the format \code{data$x[column == "a", ] <- data$y[column == "b", ]} @@ -99,15 +135,17 @@ new_block <- function(data, names, column="block"){ #' @import data.table #' @export -replace_vals <- function(data, column="block", x, y, a, b) { - if (length(a) != length(b)) { - stop("Vectors 'a' and 'b' must be of the same length") - } - setDT(data) - for (i in seq_along(a)) { - data[, (x) := as.numeric(get(x)) - ][get(column) == a[i], (x) := data[get(column) == b[i], y, with = FALSE][[1]]] - } +replace_vals <- function(data, column = "block", x, y, a, b) { + if (length(a) != length(b)) { + stop("Vectors 'a' and 'b' must be of the same length") + } + setDT(data) + for (i in seq_along(a)) { + data[, (x) := as.numeric(get(x))][ + get(column) == a[i], + (x) := data[get(column) == b[i], y, with = FALSE][[1]] + ] + } - return(data) + return(data) } diff --git a/Syndemics/air.toml b/Syndemics/air.toml new file mode 100644 index 0000000..ca2605b --- /dev/null +++ b/Syndemics/air.toml @@ -0,0 +1,11 @@ +[format] +line-width = 80 +indent-width = 4 +indent-style = "space" +line-ending = "auto" +persistent-line-breaks = true +exclude = [] +default-exclude = true +skip = [] +table = [] +default-table = true \ No newline at end of file From 6ee30f947cf1cb23072a8a6ec6ec844df3a4a8f0 Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Wed, 3 Dec 2025 11:36:17 -0500 Subject: [PATCH 2/3] fixing file names and man pages --- Syndemics/.Rbuildignore | 1 + Syndemics/NAMESPACE | 1 + Syndemics/R/{buildLifeTables.R => build_life_tables.R} | 2 +- Syndemics/R/{internal_crcTools.R => internal_crc_tools.R} | 0 Syndemics/R/{loadOutputFiles.R => load_output_files.R} | 0 Syndemics/R/residential_admissions.R | 1 + ...spond_inputManipulations.R => respond_input_manipulations.R} | 0 Syndemics/man/DSA.Rd | 2 +- Syndemics/man/Syndemics-package.Rd | 2 +- Syndemics/man/build_background_mortality_file.Rd | 2 +- Syndemics/man/change_agegrp_chunk.Rd | 2 +- Syndemics/man/create_and_fill_table.Rd | 2 +- Syndemics/man/extract_background_mortality.Rd | 2 +- Syndemics/man/formula_list.Rd | 2 +- Syndemics/man/get_filtered_data.Rd | 2 +- Syndemics/man/is.formula.Rd | 2 +- Syndemics/man/loadOutputFiles.Rd | 2 +- Syndemics/man/new_block.Rd | 2 +- Syndemics/man/replace_vals.Rd | 2 +- Syndemics/man/step_regression.Rd | 2 +- 20 files changed, 17 insertions(+), 14 deletions(-) rename Syndemics/R/{buildLifeTables.R => build_life_tables.R} (98%) rename Syndemics/R/{internal_crcTools.R => internal_crc_tools.R} (100%) rename Syndemics/R/{loadOutputFiles.R => load_output_files.R} (100%) rename Syndemics/R/{respond_inputManipulations.R => respond_input_manipulations.R} (100%) diff --git a/Syndemics/.Rbuildignore b/Syndemics/.Rbuildignore index f0b429d..617bb64 100644 --- a/Syndemics/.Rbuildignore +++ b/Syndemics/.Rbuildignore @@ -3,3 +3,4 @@ ^LICENSE\.md$ ^\.github$ inst/data +.air.toml diff --git a/Syndemics/NAMESPACE b/Syndemics/NAMESPACE index 345dde9..9c8b27c 100644 --- a/Syndemics/NAMESPACE +++ b/Syndemics/NAMESPACE @@ -31,6 +31,7 @@ importFrom(data.table,dcast) importFrom(data.table,fread) importFrom(data.table,rbindlist) importFrom(dplyr,bind_rows) +importFrom(dplyr,filter) importFrom(dplyr,left_join) importFrom(dplyr,mutate) importFrom(dplyr,rename) diff --git a/Syndemics/R/buildLifeTables.R b/Syndemics/R/build_life_tables.R similarity index 98% rename from Syndemics/R/buildLifeTables.R rename to Syndemics/R/build_life_tables.R index a0c5397..6426b08 100644 --- a/Syndemics/R/buildLifeTables.R +++ b/Syndemics/R/build_life_tables.R @@ -80,7 +80,7 @@ extract_background_mortality <- function( year_deaths := as.numeric(year_deaths) ] - bin_groups <- (seq(nrow(dt)) - 1) %/% bin_size + bin_groups <- (seq_len(nrow(dt)) - 1) %/% bin_size deaths_by_group <- dt[, sum(year_deaths), by = bin_groups][, V1] # 100k originates from the CDC NVSS data - reported in rates per 100,000 persons diff --git a/Syndemics/R/internal_crcTools.R b/Syndemics/R/internal_crc_tools.R similarity index 100% rename from Syndemics/R/internal_crcTools.R rename to Syndemics/R/internal_crc_tools.R diff --git a/Syndemics/R/loadOutputFiles.R b/Syndemics/R/load_output_files.R similarity index 100% rename from Syndemics/R/loadOutputFiles.R rename to Syndemics/R/load_output_files.R diff --git a/Syndemics/R/residential_admissions.R b/Syndemics/R/residential_admissions.R index 89be6c2..942cfc1 100644 --- a/Syndemics/R/residential_admissions.R +++ b/Syndemics/R/residential_admissions.R @@ -8,6 +8,7 @@ #' #' @return Numeric. Average number of filtered admissions per month. #' @importFrom tibble as_tibble +#' @importFrom dplyr filter #' @export #' #' @examples diff --git a/Syndemics/R/respond_inputManipulations.R b/Syndemics/R/respond_input_manipulations.R similarity index 100% rename from Syndemics/R/respond_inputManipulations.R rename to Syndemics/R/respond_input_manipulations.R diff --git a/Syndemics/man/DSA.Rd b/Syndemics/man/DSA.Rd index ccbd8d9..618b71d 100644 --- a/Syndemics/man/DSA.Rd +++ b/Syndemics/man/DSA.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/respond_inputManipulations.R +% Please edit documentation in R/respond_input_manipulations.R \name{DSA} \alias{DSA} \title{A Function to Change RESPOND inputs from base-case by some percent change} diff --git a/Syndemics/man/Syndemics-package.Rd b/Syndemics/man/Syndemics-package.Rd index 1394ace..ed7d603 100644 --- a/Syndemics/man/Syndemics-package.Rd +++ b/Syndemics/man/Syndemics-package.Rd @@ -24,7 +24,7 @@ Authors: \item Ryan O'Dea \email{ryan.odea@bmc.org} \item Dimitri Baptiste \email{dimitri.baptiste@bmc.org} \item Hana Zwick \email{hana.zwick@bmc.org} - \item Alexandra Purdy \email{alexandra.purdy@bmc.org} + \item Alexandra Purdy } } diff --git a/Syndemics/man/build_background_mortality_file.Rd b/Syndemics/man/build_background_mortality_file.Rd index 3e0ddd3..57bba7c 100644 --- a/Syndemics/man/build_background_mortality_file.Rd +++ b/Syndemics/man/build_background_mortality_file.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/buildLifeTables.R +% Please edit documentation in R/build_life_tables.R \name{build_background_mortality_file} \alias{build_background_mortality_file} \title{Taking in the CDC NVSS Yearly life tables, extract and build the background mortality table expected by RESPOND} diff --git a/Syndemics/man/change_agegrp_chunk.Rd b/Syndemics/man/change_agegrp_chunk.Rd index d86b62b..77fd4db 100644 --- a/Syndemics/man/change_agegrp_chunk.Rd +++ b/Syndemics/man/change_agegrp_chunk.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/respond_inputManipulations.R +% Please edit documentation in R/respond_input_manipulations.R \name{change_agegrp_chunk} \alias{change_agegrp_chunk} \title{A function to change default age groups from RESPOND shell tables} diff --git a/Syndemics/man/create_and_fill_table.Rd b/Syndemics/man/create_and_fill_table.Rd index 244f25b..5617d4e 100644 --- a/Syndemics/man/create_and_fill_table.Rd +++ b/Syndemics/man/create_and_fill_table.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/buildLifeTables.R +% Please edit documentation in R/build_life_tables.R \name{create_and_fill_table} \alias{create_and_fill_table} \title{Create and fill the table with mortality values for all demographic combinations} diff --git a/Syndemics/man/extract_background_mortality.Rd b/Syndemics/man/extract_background_mortality.Rd index 11a73b6..6c53c57 100644 --- a/Syndemics/man/extract_background_mortality.Rd +++ b/Syndemics/man/extract_background_mortality.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/buildLifeTables.R +% Please edit documentation in R/build_life_tables.R \name{extract_background_mortality} \alias{extract_background_mortality} \title{Function used to extract background mortality values based on age from a single yearly CDC NVSS life table} diff --git a/Syndemics/man/formula_list.Rd b/Syndemics/man/formula_list.Rd index 73b5c00..a1bd313 100644 --- a/Syndemics/man/formula_list.Rd +++ b/Syndemics/man/formula_list.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/internal_crcTools.R +% Please edit documentation in R/internal_crc_tools.R \name{formula_list} \alias{formula_list} \title{Generates All Possible Combination of Interaction Terms diff --git a/Syndemics/man/get_filtered_data.Rd b/Syndemics/man/get_filtered_data.Rd index e8f2681..d2326a4 100644 --- a/Syndemics/man/get_filtered_data.Rd +++ b/Syndemics/man/get_filtered_data.Rd @@ -9,7 +9,7 @@ get_filtered_data(data, pattern, ignore_case = TRUE) \arguments{ \item{data}{A \code{data.table} containing a \code{source_file} column.} -\item{pattern}{A character string containing a regular expression pattern to match +\item{pattern}{A character string containing a regular expression pattern to match against the \code{source_file} column.} \item{ignore_case}{Logical; if TRUE, pattern matching is case-insensitive. Default is TRUE.} diff --git a/Syndemics/man/is.formula.Rd b/Syndemics/man/is.formula.Rd index 41092d9..b73d780 100644 --- a/Syndemics/man/is.formula.Rd +++ b/Syndemics/man/is.formula.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/internal_crcTools.R +% Please edit documentation in R/internal_crc_tools.R \name{is.formula} \alias{is.formula} \title{Formula Objects diff --git a/Syndemics/man/loadOutputFiles.Rd b/Syndemics/man/loadOutputFiles.Rd index ed95c0d..f150d74 100644 --- a/Syndemics/man/loadOutputFiles.Rd +++ b/Syndemics/man/loadOutputFiles.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/loadOutputFiles.R +% Please edit documentation in R/load_output_files.R \name{loadOutputFiles} \alias{loadOutputFiles} \title{Aggregate selected tables from a set of RESPOND simulation runs} diff --git a/Syndemics/man/new_block.Rd b/Syndemics/man/new_block.Rd index 8eaceed..d65d26e 100644 --- a/Syndemics/man/new_block.Rd +++ b/Syndemics/man/new_block.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/respond_inputManipulations.R +% Please edit documentation in R/respond_input_manipulations.R \name{new_block} \alias{new_block} \title{A function to create new blocks for RESPOND (clones 'No_Treatment' blocks and reassigns the name)} diff --git a/Syndemics/man/replace_vals.Rd b/Syndemics/man/replace_vals.Rd index 9caf1ce..e59ff80 100644 --- a/Syndemics/man/replace_vals.Rd +++ b/Syndemics/man/replace_vals.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/respond_inputManipulations.R +% Please edit documentation in R/respond_input_manipulations.R \name{replace_vals} \alias{replace_vals} \title{A function to change values to another block; follows the format \code{data$x[column == "a", ] <- data$y[column == "b", ]}} diff --git a/Syndemics/man/step_regression.Rd b/Syndemics/man/step_regression.Rd index 8f0a5c2..ed32aac 100644 --- a/Syndemics/man/step_regression.Rd +++ b/Syndemics/man/step_regression.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/internal_crcTools.R +% Please edit documentation in R/internal_crc_tools.R \name{step_regression} \alias{step_regression} \title{Helper function for stepwise regression} From 5401a7ee89b11105d90bd90fded4dc161e5948b3 Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Wed, 3 Dec 2025 12:12:55 -0500 Subject: [PATCH 3/3] Saving a basic test for proof of concept --- .gitignore | 3 +++ Syndemics/DESCRIPTION | 4 +++- Syndemics/tests/testthat.R | 12 ++++++++++++ Syndemics/tests/testthat/test-build_life_tables.R | 15 +++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 Syndemics/tests/testthat.R create mode 100644 Syndemics/tests/testthat/test-build_life_tables.R diff --git a/.gitignore b/.gitignore index b9fc0ff..ef82ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Editors +.vscode/ + # History files .Rhistory .Rapp.history diff --git a/Syndemics/DESCRIPTION b/Syndemics/DESCRIPTION index 1ecbcf9..44a2ea0 100644 --- a/Syndemics/DESCRIPTION +++ b/Syndemics/DESCRIPTION @@ -52,7 +52,9 @@ Suggests: doParallel, foreach, knitr, - rmarkdown + rmarkdown, + testthat (>= 3.0.0) VignetteBuilder: knitr URL: https://github.com/SyndemicsLab/Syndemics BugReports: https://github.com/SyndemicsLab/Syndemics/issues +Config/testthat/edition: 3 diff --git a/Syndemics/tests/testthat.R b/Syndemics/tests/testthat.R new file mode 100644 index 0000000..2bafbdc --- /dev/null +++ b/Syndemics/tests/testthat.R @@ -0,0 +1,12 @@ +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview +# * https://testthat.r-lib.org/articles/special-files.html + +library(testthat) +library(Syndemics) + +test_check("Syndemics") diff --git a/Syndemics/tests/testthat/test-build_life_tables.R b/Syndemics/tests/testthat/test-build_life_tables.R new file mode 100644 index 0000000..ebae8b6 --- /dev/null +++ b/Syndemics/tests/testthat/test-build_life_tables.R @@ -0,0 +1,15 @@ +################################################################################ +# File: test-build_life_tables.R # +# Project: Syndemics # +# Created Date: 2025-12-03 # +# Author: Matthew Carroll # +# ----- # +# Last Modified: 2025-12-03 # +# Modified By: Matthew Carroll # +# ----- # +# Copyright (c) 2025 Syndemics Lab at Boston Medical Center # +################################################################################ + +test_that("extract_background_mortality", { + expect_equal(2 * 2, 4) +})