Nothing
# Tests for IPTW functionality
# Create test data (keeping this synthetic for testing purposes)
create_iptw_test_data <- function(n = 500) {
set.seed(42)
# Generate correlated covariates similar to cachar_sample structure
age <- round(rnorm(n, 45, 12))
age <- pmax(18, pmin(75, age)) # Realistic age range
sex <- factor(sample(c("male", "female"), n, replace = TRUE, prob = c(0.76, 0.24)),
levels = c("male", "female"))
residence <- factor(sample(c("rural", "urban", "urban slum"), n, replace = TRUE, prob = c(0.87, 0.10, 0.03)),
levels = c("rural", "urban", "urban slum"))
# Generate treatment with realistic propensity score model (areca nut use)
logit_ps <- -1.2 + 0.02 * (age - 45) + 0.3 * (sex == "male") +
0.2 * (residence == "urban") + rnorm(n, 0, 0.3)
ps_true <- plogis(logit_ps)
areca_nut <- factor(rbinom(n, 1, ps_true), levels = c(0, 1), labels = c("No", "Yes"))
# Generate outcome (abnormal screening)
logit_outcome <- -2.8 + 0.8 * (areca_nut == "Yes") + 0.015 * (age - 45) +
0.4 * (sex == "male") + 0.2 * (residence == "urban")
abnormal_screen <- rbinom(n, 1, plogis(logit_outcome))
data.frame(
id = 1:n,
age = age,
sex = sex,
residence = residence,
areca_nut = areca_nut,
abnormal_screen = abnormal_screen
)
}
test_that("calc_iptw_weights works with basic inputs", {
data <- create_iptw_test_data()
result <- calc_iptw_weights(
data = data,
treatment = "areca_nut",
covariates = c("age", "sex", "residence")
)
expect_s3_class(result, "iptw_result")
expect_true(is.list(result))
expect_true(all(c("data", "ps_model", "weights", "ps", "diagnostics") %in% names(result)))
expect_equal(length(result$weights), nrow(data))
expect_true(all(result$weights > 0))
})
test_that("calc_iptw_weights handles different weight types", {
data <- create_iptw_test_data()
# Test ATE weights
result_ate <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), weight_type = "ATE")
expect_equal(result_ate$weight_type, "ATE")
# Test ATT weights
result_att <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), weight_type = "ATT")
expect_equal(result_att$weight_type, "ATT")
# Test ATC weights
result_atc <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), weight_type = "ATC")
expect_equal(result_atc$weight_type, "ATC")
# Weights should be different
expect_false(identical(result_ate$weights, result_att$weights))
expect_false(identical(result_ate$weights, result_atc$weights))
})
test_that("calc_iptw_weights handles different propensity score methods", {
data <- create_iptw_test_data()
# Test logistic (default)
result_logit <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), method = "logistic")
expect_equal(result_logit$method, "logistic")
# Test probit
result_probit <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), method = "probit")
expect_equal(result_probit$method, "probit")
# Test cloglog
result_cloglog <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), method = "cloglog")
expect_equal(result_cloglog$method, "cloglog")
})
test_that("calc_risk_diff_iptw works with basic inputs", {
data <- create_iptw_test_data()
result <- calc_risk_diff_iptw(
data = data,
outcome = "abnormal_screen",
treatment = "areca_nut",
covariates = c("age", "sex", "residence")
)
expect_s3_class(result, "riskdiff_iptw_result")
expect_true(is.data.frame(result))
expect_equal(nrow(result), 1)
expect_true(all(c("treatment_var", "rd_iptw", "ci_lower", "ci_upper", "p_value", "weight_type") %in% names(result)))
expect_true(!is.na(result$rd_iptw))
})
test_that("calc_risk_diff_iptw works with pre-calculated weights", {
data <- create_iptw_test_data()
# Calculate weights separately
iptw_result <- calc_iptw_weights(data, "areca_nut", c("age", "sex"))
# Use pre-calculated weights
result <- calc_risk_diff_iptw(
data = data,
outcome = "abnormal_screen",
treatment = "areca_nut",
covariates = c("age", "sex"),
iptw_weights = iptw_result$weights
)
expect_s3_class(result, "riskdiff_iptw_result")
expect_true(!is.na(result$rd_iptw))
})
test_that("calc_risk_diff_iptw works with bootstrap CI", {
data <- create_iptw_test_data(n = 200) # Smaller sample for faster testing
result <- calc_risk_diff_iptw(
data = data,
outcome = "abnormal_screen",
treatment = "areca_nut",
covariates = c("age", "sex"),
bootstrap_ci = TRUE,
boot_n = 100 # Small number for testing
)
expect_s3_class(result, "riskdiff_iptw_result")
expect_true(attr(result, "bootstrap"))
expect_equal(attr(result, "boot_n"), 100)
})
test_that("check_iptw_assumptions works", {
data <- create_iptw_test_data()
iptw_result <- calc_iptw_weights(data, "areca_nut", c("age", "sex"))
assumptions <- check_iptw_assumptions(iptw_result, verbose = FALSE)
expect_s3_class(assumptions, "iptw_assumptions")
expect_true(is.list(assumptions))
expect_true(all(c("overall_assessment", "positivity", "balance", "weights", "recommendations") %in% names(assumptions)))
expect_true(assumptions$overall_assessment %in% c("PASS", "CAUTION", "FAIL"))
})
test_that("IPTW functions validate inputs correctly", {
data <- create_iptw_test_data()
# Missing treatment variable
expect_error(
calc_iptw_weights(data, "missing_treatment", c("age", "sex")),
"Variables not found"
)
# Invalid weight type
expect_error(
calc_iptw_weights(data, "areca_nut", c("age", "sex"), weight_type = "invalid"),
"must be one of"
)
# Invalid method
expect_error(
calc_iptw_weights(data, "areca_nut", c("age", "sex"), method = "invalid"),
"must be one of"
)
# Wrong length weights
expect_error(
calc_risk_diff_iptw(data, "abnormal_screen", "areca_nut", c("age", "sex"),
iptw_weights = c(1, 2, 3)),
"Length of iptw_weights"
)
})
test_that("IPTW handles edge cases gracefully", {
# Small dataset
small_data <- create_iptw_test_data(n = 50)
result <- calc_iptw_weights(small_data, "areca_nut", c("age", "sex"))
expect_s3_class(result, "iptw_result")
# Dataset with missing values
data_missing <- create_iptw_test_data()
data_missing$age[1:50] <- NA
result_missing <- calc_iptw_weights(data_missing, "areca_nut", c("age", "sex"))
expect_true(nrow(result_missing$data) < nrow(data_missing))
})
test_that("print methods work for IPTW objects", {
data <- create_iptw_test_data()
# Test iptw_result print
iptw_result <- calc_iptw_weights(data, "areca_nut", c("age", "sex"))
expect_output(print(iptw_result), "Inverse Probability of Treatment Weighting")
expect_output(print(iptw_result), "Propensity Score Model")
# Test riskdiff_iptw_result print
rd_result <- calc_risk_diff_iptw(data, "abnormal_screen", "areca_nut", c("age", "sex"))
expect_output(print(rd_result), "IPTW-Standardized Risk Difference")
expect_output(print(rd_result), "Risk in Treated")
# Test summary method
expect_output(summary(rd_result), "IPTW Risk Difference Analysis Summary")
})
test_that("stabilized vs unstabilized weights differ appropriately", {
data <- create_iptw_test_data()
# Unstabilized weights
result_unstab <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), stabilize = FALSE)
# Stabilized weights
result_stab <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), stabilize = TRUE)
# Weights should be different
expect_false(identical(result_unstab$weights, result_stab$weights))
# Stabilized weights should generally have smaller variance
expect_true(stats::var(result_stab$weights) <= stats::var(result_unstab$weights))
})
test_that("weight trimming works correctly", {
data <- create_iptw_test_data()
# Without trimming
result_no_trim <- calc_iptw_weights(data, "areca_nut", c("age", "sex"), trim_weights = FALSE)
# With trimming
result_trim <- calc_iptw_weights(data, "areca_nut", c("age", "sex"),
trim_weights = TRUE, trim_quantiles = c(0.05, 0.95))
# Range of trimmed weights should be smaller or equal
expect_true(diff(range(result_trim$weights)) <= diff(range(result_no_trim$weights)))
# Check that extreme values are actually trimmed
q05 <- stats::quantile(result_no_trim$weights, 0.05)
q95 <- stats::quantile(result_no_trim$weights, 0.95)
expect_true(all(result_trim$weights >= q05))
expect_true(all(result_trim$weights <= q95))
})
test_that("create_balance_plots handles missing ggplot2 gracefully", {
data <- create_iptw_test_data()
iptw_result <- calc_iptw_weights(data, "areca_nut", c("age", "sex"))
# This should work whether ggplot2 is available or not
plots <- create_balance_plots(iptw_result, plot_type = "love")
# Should return something (either ggplot object or message)
expect_true(!is.null(plots))
})
test_that("different estimands give sensible results", {
data <- create_iptw_test_data()
# Calculate all three estimands
rd_ate <- calc_risk_diff_iptw(data, "abnormal_screen", "areca_nut", c("age", "sex"), weight_type = "ATE")
rd_att <- calc_risk_diff_iptw(data, "abnormal_screen", "areca_nut", c("age", "sex"), weight_type = "ATT")
rd_atc <- calc_risk_diff_iptw(data, "abnormal_screen", "areca_nut", c("age", "sex"), weight_type = "ATC")
# All should be valid
expect_false(is.na(rd_ate$rd_iptw))
expect_false(is.na(rd_att$rd_iptw))
expect_false(is.na(rd_atc$rd_iptw))
# They don't have to be equal (and usually won't be)
expect_true(is.numeric(rd_ate$rd_iptw))
expect_true(is.numeric(rd_att$rd_iptw))
expect_true(is.numeric(rd_atc$rd_iptw))
})
test_that("alpha level affects confidence intervals appropriately", {
data <- create_iptw_test_data()
# 95% CI
result_95 <- calc_risk_diff_iptw(data, "abnormal_screen", "areca_nut", c("age", "sex"), alpha = 0.05)
# 90% CI
result_90 <- calc_risk_diff_iptw(data, "abnormal_screen", "areca_nut", c("age", "sex"), alpha = 0.10)
# 90% CI should be narrower
width_95 <- result_95$ci_upper - result_95$ci_lower
width_90 <- result_90$ci_upper - result_90$ci_lower
expect_true(width_90 < width_95)
expect_equal(attr(result_90, "alpha"), 0.10)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.