Skip to content

fix(summary): handle single fixed-effect row in print.bmmfit summary#369

Open
GidonFrischkorn wants to merge 1 commit into
developfrom
fix-summary-single-coefficient
Open

fix(summary): handle single fixed-effect row in print.bmmfit summary#369
GidonFrischkorn wants to merge 1 commit into
developfrom
fix-summary-single-coefficient

Conversation

@GidonFrischkorn

Copy link
Copy Markdown
Collaborator

Summary

summary() errors when a fitted model has only one population-level regression coefficient. The "Regression Coefficients" block of print.bmmsummary selects rows with sapply() followed by apply(include, 1, any). With a single fixed-effect row, sapply() simplifies to a vector, so apply() receives a dimensionless object and fails:

Regression Coefficients:
Error in apply(include, 1, any) : dim(X) must have a positive length

This replaces that selection with a shape-stable Reduce("|", lapply(...)) (plus drop = FALSE), moved into a small unit-tested helper. Output is identical for models with several coefficient rows.

Cause

select_pars() returns the union of the model parameters and the predicted parameters, e.g. c("dprime", "sdratio"). The printer then marks which rows of x$fixed match any of them:

include <- sapply(paste0(pars_to_print, "_"), function(p) grepl(p, rownames(x$fixed)))
include <- apply(include, 1, any)

When x$fixed has one row, each grepl() returns length 1, so sapply() returns a length-n_pars vector instead of an n_rows x n_pars matrix, and apply(..., 1, any) fails. A single printed parameter collapses the same way.

Fix

.summary_fixed_rows <- function(fixed, pars) {
  patterns <- paste0(pars, "_")
  include <- Reduce(`|`, lapply(patterns, function(p) grepl(p, rownames(fixed))))
  fixed[include, , drop = FALSE]
}

lapply() always returns per-pattern logical vectors of length nrow(fixed); Reduce("|", ...) ORs them into one vector for any row or parameter count; drop = FALSE keeps a single matched row a data frame.

Tests

Two regression tests in tests/testthat/test-summary.R that need no fitted-model fixture (the existing summary test is gated on a real fit, which is why this slipped through): one reproduces the single-row failure, one confirms multi-parameter selection is unchanged.

Relation to the SDT PRs

This is a general bug in core summary.R, so it is a standalone PR off develop rather than part of a model PR. The SDT model stack (sdt_binarysdt_mafcsdt_rankingsdt_rating) is what exposed it. These are the first bmm models that produce a summary with a single population-level coefficient, because they fix nuisance parameters and estimate only dprime. For example, sdt_ranking(dist = "gumbel_min") and sdt_mafc fit as dprime ~ 1 (+ (1 | id)), leaving one estimated coefficient while select_pars() still lists dprime plus the fixed sdratio/mu. Earlier models always had at least two fixed rows, so the flaw never triggered.

The fix is in core code, so every model benefits (any intercept-only single-parameter fit), and the SDT branches will pick it up when rebased onto develop or at merge. They do not need it to build or pass their own tests; they need it only for summary() to print on the gumbel-min ranking and m-AFC examples.

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant