#' Create a 2x2 contingency table with odds calculation (vectorized for mutate)
#'
#' @param a numeric vector - top-left cell values
#' @param b numeric vector - top-right cell values
#' @param c numeric vector - bottom-left cell values
#' @param d numeric vector - bottom-right cell values
#' @param row_names character vector of length 2 - row header names (default: c("Row 1", "Row 2"))
#' @param col_names character vector of length 2 - column header names (default: c("Col 1", "Col 2"))
#' @param table_title character - title for the table (default: "2x2 Contingency Table with Odds")
#'
#' @return gt table object with vectorized input data and calculated odds
#'
#' @examples
#' df = data.frame(
#' study = c("Study 1", "Study 2", "Study 3"),
#' a = c(10, 8, 12),
#' b = c(20, 12, 18),
#' c = c(5, 6, 4),
#' d = c(15, 10, 16)
#' )
#'
#' df |>
#' dplyr::mutate(
#' odds_table = purrr::pmap(
#' list(a,b,c,d),function(a,b,c,d){
#' create_odds_table(
#' a,b,c,d,
#' row_names = c("Exposed", "Not Exposed"),
#' col_names = c("Case", "Control"))
#' }
#' )
#' )
create_odds_table <- function(a, b, c, d,
row_names = c("Row 1", "Row 2"),
col_names = c("Col 1", "Col 2"),
table_title = "2x2 Contingency Table with Odds") {
stopifnot(length(a)==length(b) &
length(b)==length(c) &
length(c)==length(d) &
length(d)==1)
# Calculate odds for all values
odds <- (a * d) / (b * c)
odds_rounded <- as.character(round(odds, 2))
# Create a single table with all the vectorized data
table_data <- data.frame(
Variable = c(row_names[1], row_names[2], "Odds Ratio"),
Col1 = c(a, c, paste0("(", a, " × ", d, ") / (", b, " × ", c, ")")),
Col2 = c(b, d, odds_rounded),
stringsAsFactors = FALSE
)
# Set column names
names(table_data)[2:3] <- col_names
# Create gt table
gt_table <- table_data |>
gt::gt() |>
gt::tab_header(title = table_title) |>
gt::tab_style(
style = gt::cell_text(weight = "bold"),
locations = gt::cells_column_labels()
) |>
gt::tab_style(
style = gt::cell_text(weight = "bold"),
locations = gt::cells_body(columns = 1)
) |>
gt::cols_align(
align = "center",
columns = 2:3
)
# Add styling for odds ratio rows
gt_table <- gt_table |>
gt::tab_style(
style = list(
gt::cell_fill(color = "lightgray"),
gt::cell_text(weight = "bold")
),
locations = gt::cells_body(rows = 3)
) |>
gt::tab_footnote(
footnote = paste0("Odds Ratio = ", odds_rounded,
" (calculated as (a×d)/(b×c))"),
locations = gt::cells_body(columns = 2, rows = 3)
)
return(gt_table)
}