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

Prepare CRAN release #369

Merged
merged 46 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
bb30d84
Prepare CRAN release
strengejacke Jan 27, 2025
1f1fd01
Merge branch 'main' into rc_0_9_0d
strengejacke Jan 28, 2025
714c346
Merge branch 'main' into rc_0_9_0d
strengejacke Jan 28, 2025
f925df0
Merge branch 'main' into rc_0_9_0d
strengejacke Jan 28, 2025
ed728a1
Merge branch 'main' into rc_0_9_0d
strengejacke Jan 28, 2025
c159232
Merge branch 'main' into rc_0_9_0d
strengejacke Jan 29, 2025
640555c
styler
strengejacke Jan 29, 2025
c27efc8
structure code
strengejacke Jan 29, 2025
9aa333a
Merge branch 'main' into rc_0_9_0d
strengejacke Jan 29, 2025
9ed9c8d
comment code, simplify code
strengejacke Jan 29, 2025
ce48278
Merge branch 'rc_0_9_0d' of https://github.com/easystats/modelbased i…
strengejacke Jan 29, 2025
e79ae75
minor print
strengejacke Jan 29, 2025
1dd853e
Merge branch 'main' into rc_0_9_0d
strengejacke Jan 30, 2025
3fc66f6
Update get_marginalmeans.R
strengejacke Jan 31, 2025
fcf5ca7
fix issues with latest marginaleffects, update tests
strengejacke Jan 31, 2025
b36a716
Update get_marginaltrends.R
strengejacke Jan 31, 2025
211f61a
update readme
strengejacke Jan 31, 2025
8b1c1a0
update test
strengejacke Jan 31, 2025
ca99c54
fix johnson neymann
strengejacke Jan 31, 2025
669d9a2
update tests
strengejacke Jan 31, 2025
478415d
update readme
strengejacke Jan 31, 2025
adf6ea1
update readme
strengejacke Jan 31, 2025
b8e6167
fix
strengejacke Jan 31, 2025
587f9bc
Update DESCRIPTION
strengejacke Jan 31, 2025
36bca20
styler
strengejacke Jan 31, 2025
44bfc09
Merge branch 'main' into rc_0_9_0d
strengejacke Feb 1, 2025
3ce2b81
remotes
strengejacke Feb 1, 2025
98b3a46
rename marginalization -> estimate
strengejacke Feb 3, 2025
2ba7273
"average" -> "sample"
strengejacke Feb 4, 2025
7fc5c8d
Update WORDLIST
strengejacke Feb 4, 2025
33f24d2
Update get_marginalcontrasts.R
strengejacke Feb 4, 2025
20c82ed
update snapshots
strengejacke Feb 4, 2025
edf27e7
update snapshots
strengejacke Feb 4, 2025
e2a2107
update
strengejacke Feb 4, 2025
7aa93cb
Fix #377
strengejacke Feb 4, 2025
9f14396
fix test
strengejacke Feb 4, 2025
4c5b801
fix
strengejacke Feb 4, 2025
7f3ff3e
harmonize order of arguments
strengejacke Feb 4, 2025
5be9797
typoe
strengejacke Feb 4, 2025
8284a3f
styler
strengejacke Feb 4, 2025
bd64e61
add ATT/ATU/ATE options
strengejacke Feb 4, 2025
865ab20
more informative error for g-computation
strengejacke Feb 5, 2025
afb4c25
minor
strengejacke Feb 5, 2025
998d519
lintr
strengejacke Feb 5, 2025
9d7b96f
add test
strengejacke Feb 5, 2025
d9afd23
add test
strengejacke Feb 5, 2025
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
6 changes: 3 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: modelbased
Title: Estimation of Model-Based Predictions, Contrasts and Means
Version: 0.8.9.107
Version: 0.9.0
Authors@R:
c(person(given = "Dominique",
family = "Makowski",
Expand Down Expand Up @@ -63,8 +63,9 @@ Suggests:
lmerTest,
logspline,
MASS,
marginaleffects,
marginaleffects (>= 0.25.0),
mgcv,
nanoparquet,
performance (>= 0.13.0),
patchwork,
pbkrtest,
Expand All @@ -89,4 +90,3 @@ Roxygen: list(markdown = TRUE)
Config/Needs/check: stan-dev/cmdstanr
Config/Needs/website: easystats/easystatstemplate
LazyData: true
Remotes: vincentarelbundock/marginaleffects
10 changes: 7 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
- Argument `fixed` has been removed, as you can fix predictor at certain values
using the `by` argument.

- Argument `transform` is deprecated. Please use `predict` instead.
- Argument `transform` is no longer used to determine the scale of the predictions.
Please use `predict` instead.

- Argument `transform` is now used to (back-) transform predictions and confidence
intervals.

- Argument `method` in `estimate_contrasts()` was renamed into `comparison`.

Expand All @@ -35,8 +39,8 @@
predictions should be on the response scale, link scale, etc.). It can also
be used to predict auxiliary (distributional) parameters.

- `estimate_means()` and `estimate_contrasts()` get a `marginalize` argument,
to specify how to marginalize over non-focal terms. This results in slightly
- `estimate_means()` and `estimate_contrasts()` get a `estimate` argument,
to specify how to estimate over non-focal terms. This results in slightly
different predicted values, each approach answering a different question.

- `estimate_contrasts()` gains a `backend` argument. This defaults to
Expand Down
17 changes: 6 additions & 11 deletions R/estimate_contrasts.R
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,13 @@ estimate_contrasts.default <- function(model,
by = NULL,
predict = NULL,
ci = 0.95,
p_adjust = "none",
comparison = "pairwise",
marginalize = "average",
backend = getOption("modelbased_backend", "marginaleffects"),
estimate = "average",
p_adjust = "none",
transform = NULL,
backend = getOption("modelbased_backend", "marginaleffects"),
verbose = TRUE,
...) {
## TODO: remove deprecation warning later
if (!is.null(transform)) {
insight::format_warning("Argument `transform` is deprecated. Please use `predict` instead.")
predict <- transform
}

if (backend == "emmeans") {
# Emmeans ------------------------------------------------------------------
estimated <- get_emcontrasts(model,
Expand All @@ -138,7 +132,8 @@ estimate_contrasts.default <- function(model,
comparison = comparison,
p_adjust = p_adjust,
ci = ci,
marginalize = marginalize,
estimate = estimate,
transform = transform,
verbose = verbose,
...
)
Expand All @@ -150,7 +145,7 @@ estimate_contrasts.default <- function(model,

# Table formatting
attr(out, "table_title") <- c(ifelse(
marginalize == "specific",
estimate == "specific",
"Model-based Contrasts Analysis",
"Marginal Contrasts Analysis"
), "blue")
Expand Down
69 changes: 43 additions & 26 deletions R/estimate_means.R
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,20 @@
#' packages), for instance when using complex formulae in `brms` models, the
#' `predict` argument can take the value of the parameter you want to estimate,
#' for instance `"sigma"`, `"kappa"`, etc.
#' @param marginalize Character string, indicating the type of marginalization.
#' This dictates how the predictions are "averaged" over the non-focal predictors,
#' i.e. those variables that are not specified in `by` or `contrast`.
#' @param estimate Character string, indicating the type of target population
#' predictions refer to. This dictates how the predictions are "averaged" over
#' the non-focal predictors, i.e. those variables that are not specified in
#' `by` or `contrast`.
#' - `"average"` (default): Takes the mean value for non-focal numeric
#' predictors and marginalizes over the factor levels of non-focal terms,
#' which computes a kind of "weighted average" for the values at which these
#' terms are hold constant. These predictions are a good representation of the
#' sample, because all possible values and levels of the non-focal predictors
#' are considered. It answers the question, "What is the predicted value for
#' an 'average' observation in *my data*?". It refers to randomly picking a
#' subject of your sample and the result you get on average. This approach is
#' the one taken by default in the `emmeans` package.
#' an 'average' observation in *my data*?". Cum grano salis, it refers to
#' randomly picking a subject of your sample and the result you get on
#' average. This approach is the one taken by default in the `emmeans`
#' package.
#' - `"population"`: Non-focal predictors are marginalized over the observations
#' in the sample, where the sample is replicated multiple times to produce
#' "counterfactuals" and then takes the average of these predicted values
Expand All @@ -65,15 +67,15 @@
#' your observed sample, but also "what would be if" we had more data, or if
#' we had data from a different sample.
#'
#' In other words, the distinction between marginalization types resides in whether
#' In other words, the distinction between estimate types resides in whether
#' the prediction are made for:
#' - A specific "individual" from the sample (i.e., a specific combination of
#' predictor values): this is what is obtained when using [`estimate_relation()`]
#' and the other prediction functions.
#' - An average individual from the sample: obtained with
#' `estimate_means(..., marginalize = "average")`
#' `estimate_means(..., estimate = "average")`
#' - The broader, hypothetical target population: obtained with
#' `estimate_means(..., marginalize = "population")`
#' `estimate_means(..., estimate = "population")`
#' @param backend Whether to use `"emmeans"` or `"marginaleffects"` as a backend.
#' Results are usually very similar. The major difference will be found for mixed
#' models, where `backend = "marginaleffects"` will also average across random
Expand All @@ -84,7 +86,13 @@
#' `options(modelbased_backend = "emmeans")` to use the **emmeans** package or
#' `options(modelbased_backend = "marginaleffects")` to set **marginaleffects**
#' as default backend.
#' @param transform Deprecated, please use `predict` instead.
#' @param transform A function applied to predictions and confidence intervals
#' to (back-) transform results, which can be useful in case the regression
#' model has a transformed response variable (e.g., `lm(log(y) ~ x)`). For
#' Bayesian models, this function is applied to individual draws from the
#' posterior distribution, before computing summaries. Can also be `TRUE`, in
#' which case `insight::get_transformation()` is called to determine the
#' appropriate transformation-function.
#' @param verbose Use `FALSE` to silence messages and warnings.
#' @param ... Other arguments passed, for instance, to [insight::get_datagrid()],
#' to functions from the **emmeans** or **marginaleffects** package, or to process
Expand All @@ -93,8 +101,8 @@
#' to control the (number of) representative values.
#' - **marginaleffects**: Internally used functions are `avg_predictions()` for
#' means and contrasts, and `avg_slope()` for slopes. Therefore, arguments
#' for instance like `vcov`, `transform`, `equivalence` or `slope` can be
#' passed to those functions.
#' for instance like `vcov`, `transform`, `equivalence`, `slope` or even
#' `newdata` can be passed to those functions.
#' - **emmeans**: Internally used functions are `emmeans()` and `emtrends()`.
#' Additional arguments can be passed to these functions.
#' - Bayesian models: For Bayesian models, parameters are cleaned using
Expand Down Expand Up @@ -172,30 +180,39 @@ estimate_means <- function(model,
by = "auto",
predict = NULL,
ci = 0.95,
marginalize = "average",
backend = getOption("modelbased_backend", "marginaleffects"),
estimate = "average",
transform = NULL,
backend = getOption("modelbased_backend", "marginaleffects"),
verbose = TRUE,
...) {
## TODO: remove deprecation warning later
if (!is.null(transform)) {
insight::format_warning("Argument `transform` is deprecated. Please use `predict` instead.")
predict <- transform
}

# validate input
marginalize <- insight::validate_argument(
marginalize,
estimate <- insight::validate_argument(
estimate,
c("average", "population", "specific")
)

if (backend == "emmeans") {
# Emmeans ------------------------------------------------------------------
estimated <- get_emmeans(model, by = by, predict = predict, verbose = verbose, ...)
estimated <- get_emmeans(
model,
by = by,
predict = predict,
verbose = verbose,
...
)
means <- .format_emmeans_means(estimated, model, ci = ci, verbose = verbose, ...)
} else {
# Marginalmeans ------------------------------------------------------------
estimated <- get_marginalmeans(model, by = by, predict = predict, ci = ci, marginalize = marginalize, verbose = verbose, ...) # nolint
estimated <- get_marginalmeans(
model,
by = by,
predict = predict,
ci = ci,
estimate = estimate,
transform = transform,
verbose = verbose,
...
)
means <- format(estimated, model, ...)
}

Expand All @@ -204,13 +221,13 @@ estimate_means <- function(model,

# Table formatting
attr(means, "table_title") <- c(ifelse(
marginalize == "specific",
estimate == "specific",
"Model-based Predictions",
"Estimated Marginal Means"
), "blue")
attr(means, "table_footer") <- .table_footer(
means,
type = ifelse(marginalize == "specific", "predictions", "means"),
type = ifelse(estimate == "specific", "predictions", "means"),
by = info$by,
model = model,
info = info
Expand Down
25 changes: 25 additions & 0 deletions R/estimate_predicted.R
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@
#' you are directly predicting the value of some distributional parameter), and
#' the corresponding functions will then only differ in the default value of
#' their `data` argument.
#' @param transform A function applied to predictions and confidence intervals
#' to (back-) transform results, which can be useful in case the regression
#' model has a transformed response variable (e.g., `lm(log(y) ~ x)`). Can also
#' be `TRUE`, in which case `insight::get_transformation()` is called to
#' determine the appropriate transformation-function. **Note:** Standard errors
#' are not (back-) transformed!
#' @param ... You can add all the additional control arguments from
#' [insight::get_datagrid()] (used when `data = "grid"`) and
#' [insight::get_predicted()].
Expand Down Expand Up @@ -228,6 +234,7 @@ estimate_expectation <- function(model,
by = NULL,
predict = "expectation",
ci = 0.95,
transform = NULL,
keep_iterations = FALSE,
...) {
.estimate_predicted(
Expand All @@ -237,6 +244,7 @@ estimate_expectation <- function(model,
ci = ci,
keep_iterations = keep_iterations,
predict = predict,
transform = transform,
...
)
}
Expand All @@ -249,6 +257,7 @@ estimate_link <- function(model,
by = NULL,
predict = "link",
ci = 0.95,
transform = NULL,
keep_iterations = FALSE,
...) {
# reset to NULL if only "by" was specified
Expand All @@ -263,6 +272,7 @@ estimate_link <- function(model,
ci = ci,
keep_iterations = keep_iterations,
predict = predict,
transform = transform,
...
)
}
Expand All @@ -274,6 +284,7 @@ estimate_prediction <- function(model,
by = NULL,
predict = "prediction",
ci = 0.95,
transform = NULL,
keep_iterations = FALSE,
...) {
.estimate_predicted(
Expand All @@ -283,6 +294,7 @@ estimate_prediction <- function(model,
ci = ci,
keep_iterations = keep_iterations,
predict = predict,
transform = transform,
...
)
}
Expand All @@ -294,6 +306,7 @@ estimate_relation <- function(model,
by = NULL,
predict = "expectation",
ci = 0.95,
transform = NULL,
keep_iterations = FALSE,
...) {
# reset to NULL if only "by" was specified
Expand All @@ -308,6 +321,7 @@ estimate_relation <- function(model,
ci = ci,
keep_iterations = keep_iterations,
predict = predict,
transform = transform,
...
)
}
Expand All @@ -321,6 +335,7 @@ estimate_relation <- function(model,
by = NULL,
predict = "expectation",
ci = 0.95,
transform = NULL,
keep_iterations = FALSE,
...) {
# only "by" or "data", but not both
Expand Down Expand Up @@ -445,6 +460,16 @@ estimate_relation <- function(model,
out$Residuals <- response - out$Predicted
}

# transform reponse?
if (isTRUE(transform)) {
transform <- insight::get_transformation(model, verbose = FALSE)$inverse
}
if (!is.null(transform)) {
out$Predicted <- transform(out$Predicted)
out$CI_low <- transform(out$CI_low)
out$CI_high <- transform(out$CI_high)
}

# Store relevant information
attr(out, "ci") <- ci
attr(out, "keep_iterations") <- keep_iterations
Expand Down
Loading
Loading