Skip to content
Merged
2 changes: 1 addition & 1 deletion 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.18.0.2
Version: 0.18.0.3
Authors@R:
c(person(given = "Dominique",
family = "Makowski",
Expand Down
25 changes: 22 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,35 @@

## Bug fixes

* Filters on the response categories of frequentist ordinal models with
`backend = "emmeans"`, where `Sat` is the response:
* `estimate_means()`, `estimate_contrasts()` and `estimate_slopes()` now
also filter the response categories in a list or data-frame `by`, for
example `by = list(Infl = "Low", Sat = "Low")`. Before,
`estimate_means()` and `estimate_contrasts()` returned all response
categories, and `estimate_slopes()` gave an error. With a list, a data
frame or a formula such as `by = ~ Infl + Sat`, the printed output no
longer lists the response under "Predictors modulated".
* `estimate_contrasts()` now contrasts only the named response categories,
for example `estimate_contrasts(m, "Sat = c('Low', 'High')", by = "Infl")`.
Before, it ignored the values and contrasted all categories. A single
category gives an error, and so does a filter on the response in `by`
when the response is also in `contrast`.
* For contrasts of slopes, a filter in `by` that leaves one level to
compare, for example `by = "Infl = 'Low'"`, now gives a clear error.
Before, `estimate_contrasts()` returned a table with empty contrasts.

* `estimate_contrasts()` now applies the filter values in `by` to contrasts of
slopes with `estimate = "average"` and with `backend = "emmeans"`, for
example `estimate_contrasts(m, "wt", by = c("cyl = '4'", "am"))`, where
`cyl` and `am` are factors. Before, these contrasts compared the slopes of
all levels and ignored the filter. With `backend = "emmeans"`, the filter
applies only to `by` variables that are all factors or character vectors.
If the filter leaves fewer than two slopes to compare,
`estimate_contrasts()` now stops with a clear error. Ordinal and
multinomial models, and a custom hypothesis in `comparison` (such as
`"b1 = b2"`, a function or a matrix), get no such check.
`estimate_contrasts()` now stops with a clear error. Multinomial models,
Bayesian ordinal models, frequentist ordinal models with
`backend = "marginaleffects"`, and a custom hypothesis in `comparison`
(such as `"b1 = b2"`, a function or a matrix), get no such check.

* `p_adjust = "tukey"` and `p_adjust = "sidak"` now give the same p-values as
*emmeans* in `estimate_contrasts()` and `estimate_slopes()` with
Expand Down
6 changes: 5 additions & 1 deletion R/estimate_contrasts.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
#' For contrasting slopes, the `comparison` will always be `"pairwise"`. It is
#' possible to compute pairwise comparisons of two average slopes at the levels
#' of a third variable, by also adding that variable to the `contrast` argument,
#' e.g. `contrast = c("num1", "num2", "factor")`. See 'Examples'.
#' e.g. `contrast = c("num1", "num2", "factor")`. See 'Examples'. For
#' frequentist ordinal models and `backend = "emmeans"`, `contrast` can name the
#' response with two or more categories, for example
#' `contrast = "y = c('low', 'high')"`, to contrast only these response
#' categories (with `predict = "prob"`, the default).
#' @param p_adjust The p-values adjustment method for frequentist multiple
#' comparisons. Can be one of `"none"` (default), `"hochberg"`, `"hommel"`,
#' `"bonferroni"`, `"BH"`, `"BY"`, `"fdr"`, `"tukey"`, `"sidak"`, `"sup-t"`,
Expand Down
11 changes: 6 additions & 5 deletions R/estimate_means.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
#' `by = NULL`, the grand mean of the response is predicted. For frequentist
#' ordinal models (for example from `MASS::polr()`, `ordinal::clm()` or
#' `ordinal::clmm()`), `by` can also name the response with values, for example
#' `by = c("x", "y = c('low', 'high')")`. `estimate_means()`,
#' `estimate_contrasts()` and `estimate_slopes()` then keep only the rows of
#' these response categories. This filter works with `backend = "emmeans"` and
#' `predict = "prob"` (the default).
#' `by = c("x", "y = c('low', 'high')")`, or as an element of a list or a
#' column of a data frame, for example `by = list(x = c(1, 2), y = "low")`.
#' `estimate_means()`, `estimate_contrasts()` and `estimate_slopes()` then keep
#' only the rows of these response categories. This filter works with
#' `backend = "emmeans"` and `predict = "prob"` (the default).
#' @param predict Is passed to the `type` argument in `emmeans::emmeans()` (when
#' `backend = "emmeans"`) or in `marginaleffects::avg_predictions()` (when
#' `backend = "marginaleffects"`). Valid options for `predict` are:
Expand Down Expand Up @@ -53,7 +54,7 @@
#' `Response`). The modes `"cum.prob"`, `"exc.prob"` and `"linear.predictor"`
#' return one value per threshold (column `Threshold`). For modes with
#' response categories or thresholds, contrasts compare the focal levels
#' within each one. For
#' within each one, unless `contrast` names the response. For
#' `estimate_slopes()`, the slopes for `"prob"` and `"mean.class"` are
#' computed from the slopes of the cumulative probabilities.
#'
Expand Down
19 changes: 18 additions & 1 deletion R/get_emcontrasts.R
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ get_emcontrasts <- function(
fun_args$mode <- ordinal$mode
}
.check_ordinal_response_filter(my_args$response_filter, ordinal$mode)
.check_ordinal_response_filter(my_args$response_contrast_filter, ordinal$mode, "contrast")
}

# add dots
Expand Down Expand Up @@ -110,7 +111,15 @@ get_emcontrasts <- function(
(is.character(comparison) && !.is_custom_comparison(comparison)) ||
inherits(comparison, "formula")
) {
.check_slope_contrast_filter(model, my_args$by, slope_filter)
# ordinal models: the slopes are contrasted within each response
# category or threshold (or, for `mean.class`, once per level of `by`),
# so the slopes to compare are counted from `by`
.check_slope_contrast_filter(
model,
my_args$by,
slope_filter,
within_categories = !is.null(ordinal$mode)
)
Comment thread
jmgirard marked this conversation as resolved.
Resolved
}
# Run emmeans. Filters in `by` go into `at`, so only those slopes are
# contrasted
Expand All @@ -137,6 +146,14 @@ get_emcontrasts <- function(
specs <- .add_emmeans_pseudo_factor(my_args$emmeans_specs, ordinal$pseudo_factor)
fun_args <- c(fun_args, list(specs = specs, at = my_args$emmeans_at))
estimated <- suppressMessages(do.call(emmeans::emmeans, fun_args))
# ordinal models: a `contrast` term on the response with values keeps only
# those response categories, before they are contrasted
estimated <- .filter_ordinal_contrast_grid(
estimated,
model,
ordinal$pseudo_factor,
my_args$response_contrast_filter
)
# Find by variables
emm_by <- specs[!specs %in% my_args$contrast]
if (length(emm_by) == 0) {
Expand Down
Loading
Loading