Skip to content

Add Brant test (resolves: https://github.com/jasp-stats/jasp-issues/issues/3295)#511

Open
rphars wants to merge 27 commits into
jasp-stats:masterfrom
rphars:brantTest
Open

Add Brant test (resolves: https://github.com/jasp-stats/jasp-issues/issues/3295)#511
rphars wants to merge 27 commits into
jasp-stats:masterfrom
rphars:brantTest

Conversation

@rphars

@rphars rphars commented Jun 14, 2026

Copy link
Copy Markdown

Implements the Brant test, which tests the proportional odds (also called parallel lines) assumption in ordered logit models. This resolves: jasp-stats/jasp-issues#3295

The test is described in
Brant, R. (1990). Assessing proportionality in the proportional odds model for ordinal logistic regression. Biometrics, 46(4), 1171–1178. https://doi.org/10.2307/2532457

This is a new implementation, different from earlier implementations in brant::brant and gofcat::brant.test. Several reasons for this:

  • brant::brant is not compatible with VGAM
  • gofcat::brant.test is compatible, but dependency-heavy.
  • It was a nice opportunity to learn more about the underlying logic of the test

The code adds a new menu option when ordinal logit models are selected:
branttest_screen

Outputs are tested against:
-STATA's brant (implemented by Long & Freese)
-prior R implementations from brant::brant and gofcat::brant.test.

The code outputs the same results as in STATA's brant:
branttest_vstata
with every dataset I've tried. Screenshot shows data from: https://stats.oarc.ucla.edu/r/dae/ordinal-logistic-regression/

There is one small implementation difference compared to brant::brant and gofcat::brant.test, which both omit a transpose in one specific place indicated in the code. This leads to minor numerical differences in small samples. The current implementation is consistent with STATA's brant and Brant's paper.

Note: this is my first contribution, so apologies in advance if I missed anything.

rphars and others added 27 commits June 14, 2026 11:55
@github-actions

Copy link
Copy Markdown
Contributor

👋 Friendly reminder: It looks like NEWS.md wasn't updated in this Pull Request.

If your changes include bug fixes, new features, or UI tweaks, please consider adding a quick note to the # jaspYourModule (development version) section so our users know about your awesome work! (If this is just a minor typo fix, feel free to ignore this message.)

@rphars rphars changed the title Add Brant test (resolves jasp-stats/jasp-issues#3295) Add Brant test (resolves: https://github.com/jasp-stats/jasp-issues/issues/3295) Jun 14, 2026
@shun2wang shun2wang requested a review from JohnnyDoorn June 14, 2026 13:59
@JohnnyDoorn

Copy link
Copy Markdown
Contributor

build bot build

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

✅ Build Complete!

Your JASP module bundles have been successfully built for macOS (ARM) and Windows.

👉 Click here to download the artifacts

(Scroll to the bottom of the page to find the "Artifacts" section).

@JohnnyDoorn JohnnyDoorn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice, especially as a first contribution! Just some minor suggestions:

  • Please add a note in news.md so that your change gets included in the next release notes
  • on line 1257 you have a footnote with whitespaces and indentations, which does not work for translations and the like. Please just make this one continuous string
    i.e., gettext("Negative \u03A7\u00B2 statistics are computational artifacts. They indicate the estimated covariance matrix is not positive semi-definite or is ill-conditioned, often due to small samples or sparse data. Test results might be misleading."
  • 1:numThresholds / 1:numPredictors → seq_len(...) (safe here given the guards, but it's the style-guide convention).
  • the qml logic can be smoothened out so that it works correctly on a JASP restart:
  1. GlmInputComponent.qml — make the property a binding (line 25):
    // before
    property bool isOrdinalModel: false
    // after
    property bool isOrdinalModel: family.currentValue === "other" && otherGlmModel.currentValue === "ordinalLogistic"
  2. GlmInputComponent.qml — delete both imperative assignments now that the binding does the work.

In the family DropDown's handler, drop just the one line (keep the rest of the handler):

	onCurrentValueChanged:
	{
		isOrdinalModel = (family.currentValue === "other") && (otherGlmModel.currentValue === "ordinalLogistic");   // ← delete this line
		if (!familyMap[currentValue].includes(link.value))
		...

In the otherGlmModel DropDown, remove the entire onCurrentValueChanged block (it exists only to set the property):

		{ label: qsTr("Firth Logistic Regression"),				value: "firthLogistic"}
		]
		onCurrentValueChanged:          // ← delete these
			{                            //    four
				isOrdinalModel = ...     //    lines
			}                            //    entirely
	}
  1. GeneralizedLinearModel.qml — tab-indent the new Group (it's a sibling of the just-closed Output group, so 2 tabs / 3 / 4), and drop the stray ; after visible:

     Group
     {
     	title:   qsTr("Assumption Checks")
     	visible: input.isOrdinalModel
    
     	CheckBox
     	{
     		name:  "brantTest"
     		label: qsTr("Brant test of proportional odds")
     	}
     }
    

return()

brantTable <- createJaspTable(title = gettext("Brant Test for Proportional Odds Assumption"))
brantTable$dependOn(options = c("dependent", "modelTerms", "otherGlmModel", "brantTest", "weights", "offset"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe also add family, link, interceptTerm to the dependencies to ensure it's updated when relevant

@rphars

rphars commented Jul 2, 2026

Copy link
Copy Markdown
Author

Thanks for the extensive review/comments. I'll implement them as soon as time allows!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: Add Brant Test to Ordinal Logistic Regression in GLM -> Other

3 participants