Nothing
box::use(
testthat[
expect_equal,
expect_error,
expect_identical,
expect_named,
expect_true,
test_that
]
)
box::use(
artma / data / derived_columns[
apply_derived_columns,
coerce_derived_value,
derived_column_names,
get_derived_specs
]
)
#' A frame with enough rows and spread for the derived-encoding correlation
#' check to have something to work with.
sample_df <- function(n = 40) {
set.seed(525)
effect <- stats::rnorm(n)
data.frame(
effect = effect,
se = abs(stats::rnorm(n)) + 0.1,
top_journal = rep(c(0, 1), length.out = n),
estimate_category = rep(c("preferred", "discounted", "other", "preferred"), length.out = n),
stringsAsFactors = FALSE
)
}
# --- get_derived_specs ------------------------------------------------------
test_that("get_derived_specs returns nothing when the option is unset", {
withr::local_options(list("artma.data.derived" = NULL))
expect_equal(length(get_derived_specs()), 0L)
})
test_that("get_derived_specs treats the NA template sentinel as empty", {
withr::local_options(list("artma.data.derived" = NA))
expect_equal(length(get_derived_specs()), 0L)
expect_equal(derived_column_names(), character(0))
})
test_that("get_derived_specs normalizes a named list into a named character vector", {
withr::local_options(list(
"artma.data.derived" = list(a = "se * 2", b = "a + 1")
))
specs <- get_derived_specs()
expect_identical(specs, c(a = "se * 2", b = "a + 1"))
expect_equal(derived_column_names(), c("a", "b"))
})
test_that("get_derived_specs rejects an unnamed entry", {
withr::local_options(list("artma.data.derived" = list("se * 2")))
expect_error(get_derived_specs(), "must be named")
})
test_that("get_derived_specs rejects a non-string expression", {
withr::local_options(list("artma.data.derived" = list(a = 12)))
expect_error(get_derived_specs(), "single R expression")
})
# --- coerce_derived_value ---------------------------------------------------
test_that("coerce_derived_value turns logicals into 0/1 integers", {
expect_identical(coerce_derived_value(c(TRUE, FALSE, NA), "d", 3), c(1L, 0L, NA_integer_))
})
test_that("coerce_derived_value recycles a scalar across the frame", {
expect_identical(coerce_derived_value(2, "d", 3), c(2, 2, 2))
})
test_that("coerce_derived_value rejects a length mismatch", {
expect_error(coerce_derived_value(c(1, 2), "d", 3), "one per row")
})
test_that("coerce_derived_value rejects a non-atomic value", {
expect_error(coerce_derived_value(list(1, 2, 3), "d", 3), "atomic vector")
})
# --- apply_derived_columns --------------------------------------------------
test_that("apply_derived_columns is a no-op when the option is unset", {
withr::local_options(list("artma.data.derived" = NA, "artma.verbose" = 1))
df <- sample_df()
expect_identical(apply_derived_columns(df), df)
})
test_that("apply_derived_columns builds an interaction term", {
withr::local_options(list(
"artma.data.derived" = list(se_x_top_journal = "se * top_journal"),
"artma.verbose" = 1
))
df <- sample_df()
result <- apply_derived_columns(df)
expect_true("se_x_top_journal" %in% names(result))
expect_equal(result$se_x_top_journal, df$se * df$top_journal)
})
test_that("apply_derived_columns builds indicators from a categorical column", {
withr::local_options(list(
"artma.data.derived" = list(
preferred = "estimate_category == 'preferred'",
discounted = "estimate_category == 'discounted'"
),
"artma.verbose" = 1
))
df <- sample_df()
result <- apply_derived_columns(df)
expect_identical(result$preferred, as.integer(df$estimate_category == "preferred"))
expect_identical(result$discounted, as.integer(df$estimate_category == "discounted"))
})
test_that("apply_derived_columns lets a later expression build on an earlier one", {
withr::local_options(list(
"artma.data.derived" = list(
preferred = "estimate_category == 'preferred'",
se_x_preferred = "se * preferred"
),
"artma.verbose" = 1
))
df <- sample_df()
result <- apply_derived_columns(df)
expect_equal(
result$se_x_preferred,
df$se * as.integer(df$estimate_category == "preferred")
)
})
test_that("apply_derived_columns rejects a name that shadows a standard column", {
withr::local_options(list(
"artma.data.derived" = list(effect = "se * 2"),
"artma.verbose" = 1
))
expect_error(apply_derived_columns(sample_df()), "shadow a standard column")
})
test_that("apply_derived_columns rejects a name already in the data", {
withr::local_options(list(
"artma.data.derived" = list(top_journal = "se * 2"),
"artma.verbose" = 1
))
expect_error(apply_derived_columns(sample_df()), "overwrite an existing column")
})
test_that("apply_derived_columns rejects a non-syntactic name", {
withr::local_options(list(
"artma.data.derived" = list("se x top journal" = "se * top_journal"),
"artma.verbose" = 1
))
expect_error(apply_derived_columns(sample_df()), "not a valid column name")
})
test_that("apply_derived_columns reports an unparseable expression", {
withr::local_options(list(
"artma.data.derived" = list(broken = "se *"),
"artma.verbose" = 1
))
expect_error(apply_derived_columns(sample_df()), "Could not parse")
})
test_that("apply_derived_columns reports an expression naming a missing column", {
withr::local_options(list(
"artma.data.derived" = list(bad = "se * nonexistent"),
"artma.verbose" = 1
))
expect_error(apply_derived_columns(sample_df()), "Failed to evaluate")
})
# --- Degenerate-moderator rejection -----------------------------------------
test_that("apply_derived_columns rejects a derived encoding of the effect", {
withr::local_options(list(
"artma.data.derived" = list(t_like = "effect / se"),
"artma.data.columns" = list(),
"artma.verbose" = 1
))
expect_error(apply_derived_columns(sample_df()), "derived encoding")
})
test_that("bma_allow_derived keeps a flagged derived column", {
withr::local_options(list(
"artma.data.derived" = list(t_like = "effect / se"),
"artma.data.columns" = list(t_like = list(var_name = "t_like", bma_allow_derived = TRUE)),
"artma.verbose" = 1
))
result <- apply_derived_columns(sample_df())
expect_true("t_like" %in% names(result))
})
test_that("bma: false keeps a flagged derived column out of the moderator check", {
withr::local_options(list(
"artma.data.derived" = list(t_like = "effect / se"),
"artma.data.columns" = list(t_like = list(var_name = "t_like", bma = FALSE)),
"artma.verbose" = 1
))
result <- apply_derived_columns(sample_df())
expect_true("t_like" %in% names(result))
})
test_that("an interaction of the standard error with a dummy is not flagged", {
withr::local_options(list(
"artma.data.derived" = list(se_x_top_journal = "se * top_journal"),
"artma.data.columns" = list(),
"artma.verbose" = 1
))
result <- apply_derived_columns(sample_df())
expect_named(
result,
c("effect", "se", "top_journal", "estimate_category", "se_x_top_journal")
)
})
# --- Schema reconciliation (#541) -------------------------------------------
#' A raw frame with everything the data pipeline treats as a required role,
#' plus one moderator to derive from.
raw_regression_df <- function(n = 40) {
set.seed(541)
data.frame(
effect = stats::rnorm(n),
se = abs(stats::rnorm(n)) + 0.1,
study_id = rep(paste0("S", 1:8), length.out = n),
n_obs = 100L,
top5_journal = rep(c(0, 1), length.out = n),
stringsAsFactors = FALSE
)
}
test_that("a derived column configured with bma reaches the BMA moderator set", {
box::use(
artma / data / schema_reconcile[reconcile_schema],
artma / methods / bma[prepare_bma_inputs]
)
raw_df <- raw_regression_df()
withr::local_options(list(
"artma.data.derived" = list(se_top5_journal = "se * top5_journal"),
"artma.data.columns" = list(
effect = list(source_name = "effect"),
se = list(source_name = "se"),
study_id = list(source_name = "study_id"),
top5_journal = list(var_name = "top5_journal", bma = TRUE),
se_top5_journal = list(var_name = "se_top5_journal", bma = TRUE)
),
"artma.data.expected_schema_columns" = colnames(raw_df),
"artma.temp.file_name" = NULL,
"artma.temp.dir_name" = NULL,
"artma.verbose" = 1
))
reconcile_schema(raw_df, mode = "auto")
config <- getOption("artma.data.columns")
expect_true(isTRUE(config$se_top5_journal$bma))
df <- apply_derived_columns(raw_df)
expect_true("se_top5_journal" %in% names(df))
prepared <- prepare_bma_inputs(
df, config,
use_vif_optimization = FALSE,
max_groups_to_remove = 3,
verbosity = 1
)
expect_true("se_top5_journal" %in% colnames(prepared$bma_data))
})
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.