Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use new dlogspline #633

Merged
merged 3 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Suggests:
knitr,
lavaan,
lme4,
logspline,
logspline (>= 2.1.21),
MASS,
mclust,
mediation,
Expand Down
44 changes: 10 additions & 34 deletions R/bayesfactor_models.R
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
cl$...$estimator <- cl$...$check_response <- NULL


names(mods) <- sapply(cl$`...`, insight::safe_deparse)

Check warning on line 180 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/bayesfactor_models.R,line=180,col=28,[keyword_quote_linter] Only quote targets of extraction with $ if necessary, i.e., if the name is not a valid R symbol (see ?make.names). Use backticks to create non-syntactic names, or use [[ to extract by string.

Check warning on line 180 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=180,col=28,[keyword_quote_linter] Only quote targets of extraction with $ if necessary, i.e., if the name is not a valid R symbol (see ?make.names). Use backticks to create non-syntactic names, or use [[ to extract by string.
names(denominator) <- insight::safe_deparse(cl$denominator)

mods <- .cleanup_BF_models(mods, denominator, cl)
Expand All @@ -196,7 +196,7 @@
supported_models[!has_terms] <- FALSE
}

objects <- .safe(do.call(insight::ellipsis_info, c(mods, verbose = FALSE)))

Check warning on line 199 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/bayesfactor_models.R,line=199,col=3,[object_overwrite_linter] 'objects' is an exported object from package 'base'. Avoid re-using such symbols.

Check warning on line 199 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=199,col=3,[object_overwrite_linter] 'objects' is an exported object from package 'base'. Avoid re-using such symbols.
if (!is.null(objects)) {
were_checked <- inherits(objects, "ListModels")

Expand Down Expand Up @@ -333,33 +333,20 @@

#' @export
bayesfactor_models.stanreg <- function(..., denominator = 1, verbose = TRUE) {
insight::check_if_installed("rstanarm")

# Organize the models and their names
mods <- list(...)
denominator <- list(denominator)

cl <- match.call(expand.dots = FALSE)
names(mods) <- sapply(cl$`...`, insight::safe_deparse)
names(denominator) <- insight::safe_deparse(cl$denominator)

mods <- .cleanup_BF_models(mods, denominator, cl)
denominator <- attr(mods, "denominator", exact = TRUE)

.bayesfactor_models_stan(mods, denominator = denominator, verbose = verbose)
}


#' @export
bayesfactor_models.brmsfit <- function(..., denominator = 1, verbose = TRUE) {
insight::check_if_installed("brms")
if (inherits(mods[[1]], "stanreg")) {
insight::check_if_installed("rstanarm")
} else if (inherits(mods[[1]], "brmsfit")) {
insight::check_if_installed("brms")
} else if (inherits(mods[[1]], "blavaan")) {
insight::check_if_installed("blavaan")

Check warning on line 342 in R/bayesfactor_models.R

View check run for this annotation

Codecov / codecov/patch

R/bayesfactor_models.R#L339-L342

Added lines #L339 - L342 were not covered by tests
}

# Organize the models and their names
mods <- list(...)
denominator <- list(denominator)

cl <- match.call(expand.dots = FALSE)
names(mods) <- sapply(cl$`...`, insight::safe_deparse)

Check warning on line 349 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/bayesfactor_models.R,line=349,col=28,[keyword_quote_linter] Only quote targets of extraction with $ if necessary, i.e., if the name is not a valid R symbol (see ?make.names). Use backticks to create non-syntactic names, or use [[ to extract by string.

Check warning on line 349 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=349,col=28,[keyword_quote_linter] Only quote targets of extraction with $ if necessary, i.e., if the name is not a valid R symbol (see ?make.names). Use backticks to create non-syntactic names, or use [[ to extract by string.
names(denominator) <- insight::safe_deparse(cl$denominator)

mods <- .cleanup_BF_models(mods, denominator, cl)
Expand All @@ -370,22 +357,11 @@


#' @export
bayesfactor_models.blavaan <- function(..., denominator = 1, verbose = TRUE) {
insight::check_if_installed("blavaan")
bayesfactor_models.brmsfit <- bayesfactor_models.stanreg

# Organize the models and their names
mods <- list(...)
denominator <- list(denominator)

cl <- match.call(expand.dots = FALSE)
names(mods) <- sapply(cl$`...`, insight::safe_deparse)
names(denominator) <- insight::safe_deparse(cl$denominator)

mods <- .cleanup_BF_models(mods, denominator, cl)
denominator <- attr(mods, "denominator", exact = TRUE)

.bayesfactor_models_stan(mods, denominator = denominator, verbose = verbose)
}
#' @export
bayesfactor_models.blavaan <- bayesfactor_models.stanreg


#' @export
Expand All @@ -397,7 +373,7 @@
mBFs <- c(0, BayesFactor::extractBF(models, TRUE, TRUE))
mforms <- sapply(c(models@denominator, models@numerator), function(x) x@shortName)

if (!inherits(models@denominator, "BFlinearModel")) {

Check warning on line 376 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/bayesfactor_models.R,line=376,col=7,[if_not_else_linter] Prefer `if (A) x else y` to the less-readable `if (!A) y else x` in a simple if/else statement.

Check warning on line 376 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=376,col=7,[if_not_else_linter] Prefer `if (A) x else y` to the less-readable `if (!A) y else x` in a simple if/else statement.
mforms <- .clean_non_linBF_mods(mforms)
} else {
mforms[mforms == "Intercept only"] <- "1"
Expand Down Expand Up @@ -458,7 +434,7 @@
out <- -outer(x$log_BF, x$log_BF, FUN = "-")
rownames(out) <- colnames(out) <- x$Model

# out <- exp(out)

Check warning on line 437 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/bayesfactor_models.R,line=437,col=5,[commented_code_linter] Remove commented code.

Check warning on line 437 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=437,col=5,[commented_code_linter] Remove commented code.

class(out) <- c("bayesfactor_models_matrix", class(out))
out
Expand All @@ -471,8 +447,8 @@
if (length(mods) == 1 && inherits(mods[[1]], "list")) {
mods <- mods[[1]]
mod_names <- tryCatch(
{

Check warning on line 450 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/bayesfactor_models.R,line=450,col=7,[unnecessary_nesting_linter] Reduce the nesting of this statement by removing the braces {}.

Check warning on line 450 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=450,col=7,[unnecessary_nesting_linter] Reduce the nesting of this statement by removing the braces {}.
sapply(cl$`...`[[1]][-1], insight::safe_deparse)

Check warning on line 451 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=451,col=19,[keyword_quote_linter] Only quote targets of extraction with $ if necessary, i.e., if the name is not a valid R symbol (see ?make.names). Use backticks to create non-syntactic names, or use [[ to extract by string.
},
error = function(e) {
NULL
Expand All @@ -483,7 +459,7 @@
}
}

if (!is.numeric(denominator[[1]])) {

Check warning on line 462 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=462,col=7,[if_not_else_linter] Prefer `if (A) x else y` to the less-readable `if (!A) y else x` in a simple if/else statement.
denominator_model <- which(names(mods) == names(denominator))

if (length(denominator_model) == 0) {
Expand Down Expand Up @@ -591,7 +567,7 @@
return(m_txt)
},
error = function(e) {
return(m_names)

Check warning on line 570 in R/bayesfactor_models.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_models.R,line=570,col=7,[return_linter] Use implicit return behavior; explicit return() is not needed.
}
)
}
Expand Down
57 changes: 25 additions & 32 deletions R/bayesfactor_parameters.R
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@
prior <- posterior
if (verbose) {
insight::format_warning(
"Prior not specified! Please specify a prior (in the form 'prior = distribution_normal(1000, 0, 1)') to get meaningful results."

Check warning on line 265 in R/bayesfactor_parameters.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/bayesfactor_parameters.R,line=265,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 136 characters.
)
}
}
Expand Down Expand Up @@ -417,9 +417,9 @@
}


sdbf <- numeric(ncol(posterior))
sdlogbf <- numeric(ncol(posterior))
for (par in seq_along(posterior)) {
sdbf[par] <- .bayesfactor_parameters(
sdlogbf[par] <- .logbayesfactor_parameters(
posterior[[par]],
prior[[par]],
direction = direction,
Expand All @@ -430,7 +430,7 @@

bf_val <- data.frame(
Parameter = colnames(posterior),
log_BF = log(sdbf),
log_BF = sdlogbf,
stringsAsFactors = FALSE
)

Expand Down Expand Up @@ -470,23 +470,23 @@


#' @keywords internal
.bayesfactor_parameters <- function(posterior,
prior,
direction = 0,
null = 0,
...) {
.logbayesfactor_parameters <- function(posterior,
prior,
direction = 0,
null = 0,
...) {
stopifnot(length(null) %in% c(1, 2))

if (isTRUE(all.equal(posterior, prior))) {
return(1)
return(0)
}

insight::check_if_installed("logspline")

if (length(null) == 1) {
relative_density <- function(samples) {
relative_loglikelihood <- function(samples) {
f_samples <- .logspline(samples, ...)
d_samples <- logspline::dlogspline(null, f_samples)
d_samples <- logspline::dlogspline(null, f_samples, log = TRUE)

if (direction < 0) {
norm_samples <- logspline::plogspline(null, f_samples)
Expand All @@ -496,36 +496,29 @@
norm_samples <- 1
}

d_samples / norm_samples
d_samples - log(norm_samples)
}

return(relative_density(prior) / relative_density(posterior))
} else if (length(null) == 2) {
null <- sort(null)
null[is.infinite(null)] <- 1.797693e+308 * sign(null[is.infinite(null)])

f_prior <- .logspline(prior, ...)
f_posterior <- .logspline(posterior, ...)

h0_prior <- diff(logspline::plogspline(null, f_prior))
h0_post <- diff(logspline::plogspline(null, f_posterior))
relative_loglikelihood <- function(samples) {
f_samples <- .logspline(samples, ...)
p_samples <- diff(logspline::plogspline(null, f_samples))

BF_null_full <- h0_post / h0_prior
if (direction < 0) {
norm_samples <- logspline::plogspline(min(null), f_samples)
} else if (direction > 0) {
norm_samples <- 1 - logspline::plogspline(max(null), f_samples)
} else {
norm_samples <- 1 - p_samples
}

if (direction < 0) {
h1_prior <- logspline::plogspline(min(null), f_prior)
h1_post <- logspline::plogspline(min(null), f_posterior)
} else if (direction > 0) {
h1_prior <- 1 - logspline::plogspline(max(null), f_prior)
h1_post <- 1 - logspline::plogspline(max(null), f_posterior)
} else {
h1_prior <- 1 - h0_prior
h1_post <- 1 - h0_post
log(p_samples) - log(norm_samples)
}
BF_alt_full <- h1_post / h1_prior

return(BF_alt_full / BF_null_full)
}

relative_loglikelihood(prior) - relative_loglikelihood(posterior)
}

# Bad Methods -------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions R/bayesfactor_restricted.R
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,13 @@ bayesfactor_restricted.data.frame <- function(posterior, hypothesis, prior = NUL

posterior_p <- sapply(posterior_l, mean)
prior_p <- sapply(prior_l, mean)
BF <- posterior_p / prior_p
log_BF <- log(posterior_p) - log(prior_p)

res <- data.frame(
Hypothesis = hypothesis,
p_prior = prior_p,
p_posterior = posterior_p,
log_BF = log(BF)
log_BF = log_BF
)

attr(res, "bool_results") <- list(posterior = posterior_l, prior = prior_l)
Expand Down
15 changes: 6 additions & 9 deletions tests/testthat/test-bayesfactor_parameters.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
test_that("bayesfactor_parameters data frame", {
skip_if_offline()
skip_if_not_or_load_if_installed("rstanarm")
skip_if_not_or_load_if_installed("BayesFactor")
skip_if_not_or_load_if_installed("httr")
skip_if_not_or_load_if_installed("brms")
skip_if_not_or_load_if_installed("logspline", "2.1.21")

Xprior <- data.frame(
x = distribution_normal(1e4),
Expand Down Expand Up @@ -59,10 +55,9 @@ test_that("bayesfactor_parameters data frame", {
test_that("bayesfactor_parameters RSTANARM", {
skip_on_cran()
skip_if_offline()
skip_if_not_or_load_if_installed("logspline", "2.1.21")
skip_if_not_or_load_if_installed("rstanarm")
skip_if_not_or_load_if_installed("BayesFactor")
skip_if_not_or_load_if_installed("httr")
skip_if_not_or_load_if_installed("brms")

fit <- suppressMessages(stan_glm(mpg ~ ., data = mtcars, refresh = 0))

Expand All @@ -72,8 +67,11 @@ test_that("bayesfactor_parameters RSTANARM", {

set.seed(333)
BF1 <- bayesfactor_parameters(fit, verbose = FALSE)
BF3 <- bayesfactor_parameters(insight::get_parameters(fit), insight::get_parameters(fit_p), verbose = FALSE)

expect_equal(BF1, BF2)
expect_equal(BF1[["Parameter"]], BF3[["Parameter"]])
expect_equal(BF1[["log_BF"]], BF3[["log_BF"]])

model_flat <- suppressMessages(
stan_glm(extra ~ group, data = sleep, prior = NULL, refresh = 0)
Expand All @@ -94,8 +92,7 @@ test_that("bayesfactor_parameters RSTANARM", {

test_that("bayesfactor_parameters BRMS", {
skip_if_offline()
skip_if_not_or_load_if_installed("rstanarm")
skip_if_not_or_load_if_installed("BayesFactor")
skip_if_not_or_load_if_installed("logspline", "2.1.21")
skip_if_not_or_load_if_installed("httr")
skip_if_not_or_load_if_installed("brms")
skip_if_not_or_load_if_installed("cmdstanr")
Expand Down
Loading