Repository navigation
Filter the response categories of ordinal models in list, data-frame and contrast terms (emmeans backend) - #695
Merged
Conversation
… (emmeans backend)
…inal slope contrasts (emmeans backend)
…; one NEWS entry
…m code rule; docs
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The numeric contrast path does not support list or data-frame by filters.
1 open issue
4 files not reviewed
man/estimate_contrasts.Rd: Generated fileman/estimate_means.Rd: Generated fileman/estimate_slopes.Rd: Generated fileman/get_emmeans.Rd: Generated file
What changed in this PR
Adds ordinal response-category filtering for by and contrast inputs with the emmeans backend.
Changes:
- Supports list, data-frame, and formula response filters.
- Filters response contrasts and handles joint tests and slope validation.
- Adds tests, documentation, NEWS updates, and a version bump.
| File | Summary |
|---|---|
tests/testthat/test-ordinal.R |
Adds filtering, contrast, joint-test, and error coverage. |
R/get_marginalcontrasts.R |
Extends ordinal slope-filter validation. |
R/get_jointtest.R |
Handles joint tests with filtered categories. |
R/get_emmeans.R |
Extracts and applies ordinal response filters. |
R/get_emcontrasts.R |
Filters contrast grids and validates slope comparisons. |
R/estimate_means.R |
Updates filtering documentation. |
R/estimate_contrasts.R |
Documents response-category contrasts. |
NEWS.md |
Records the behavioral changes. |
man/get_emmeans.Rd |
Updates generated documentation. |
man/estimate_slopes.Rd |
Updates generated documentation. |
man/estimate_means.Rd |
Updates generated documentation. |
man/estimate_contrasts.Rd |
Updates generated documentation. |
DESCRIPTION |
Bumps the development version. |
Review effort: Lite
Contributor
Author
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

With
backend = "emmeans", the response categories of ordinal models could be filtered only with a characterbysuch as"Sat='Low'". A list or data-framebythat named the response returned all categories, or an error inestimate_slopes(). Acontrastterm on the response ignored its values. A formulabylisted the response under "Predictors modulated". Abyfilter that left one level in ordinal slope contrasts printed empty contrasts.Example, with
m <- MASS::polr(Sat ~ Infl + Type, weights = Freq, data = MASS::housing, Hess = TRUE)andm2 <- MASS::polr(Sat ~ x * Infl + Type, data = d, Hess = TRUE), wheredishousingwith a numericx. All calls usebackend = "emmeans":estimate_means(m, list(Infl = c("Low", "High"), Sat = "Low"))estimate_means(m, data.frame(Infl = "Low", Sat = "Low"))estimate_slopes(m2, "x", by = list(Sat = "Low"))estimate_means(m, ~ Infl + Sat)estimate_contrasts(m, "Sat=c('Low','High')", by = "Infl")High - Low)estimate_contrasts(m, "Sat='Low'", by = "Infl")estimate_contrasts(m2, "x", by = "Infl='Low'")byleaves fewer than two slopes to compareWhat changed:
.extract_ordinal_response_filter()(R/get_emmeans.R) now reads the response from a list element, a data-frame column or a formula, as well as from a characterby. It removes the response frombyand keeps the values as the filter, so the emmeans call is the same as without the response. As for other data-frame columns, the values are crossed with the otherbyvariables. A formula has no values, so it keeps all categories.contrastterm on the response with values keeps only those categories in the emmeans grid beforeemmeans::contrast(). So comparisons that are not pairwise, such as"poly", use only the named categories. Forclmmmodels, the category codes of emmeans (1, 2, 3, ...) are matched to the category names first, with the same rule as.clean_pseudo_factor_emmeans_ordinal(). A single category gives an error, and so does a filter on the response inbywhen the response is also incontrast.comparison = "joint"with such a filter callsjoint_tests()as before. When only two categories are kept,joint_tests()fails, so the single contrast in eachbygroup is tested withemmeans::test(joint = TRUE).get_emcontrasts()now runs the "at least two slopes" check for ordinal models, because emmeans contrasts the slopes within each response category, so the slopes to compare are the levels ofby. The marginaleffects backend still skips ordinal models.byandcontrastdocs, the NEWS entry, and the version bump. The NEWS entry for the slope filters now names the models that skip the check.Tests in
test-ordinal.Rcompare each filtered result with the matching rows of the unfiltered call (polr, clm, and clmm with letter categories). The joint test is compared withemmeans::test(joint = TRUE). The tests also cover the errors (unknown categories,predict = "cum.prob", one category, the response in bothbyandcontrast) and the footer.Not fixed here, the same as on main:
"Sat [Low]"or"Infl [Low, High]"stop with "not found in the data" for any variable.comparison = "consecutive"stops with "Contrast function 'consecutive.emmc' not found", but"consec"works.clmmresponse contrasts label rows with the emmeans codes (rating1,rating2), not the category names.bysuch aslist(Infl = c("Low", "High"))does not filter.factor()response,contrast = "S2=c('Low','High')"stops with "No variable named S2 in the reference grid".byfilter that keeps one level in slope contrasts stops with "No contrasts to show".