library(rENA)
rows <- data.frame(
unit = rep(paste0("U", 1:6), each = 4),
conv = rep(rep(c("c1", "c2"), each = 2), times = 6),
grp = rep(c("g1", "g2"), each = 12),
score = rep(c(10, 20, 30, 40, 50, 60), each = 4),
A = c(1,0,1,0, 0,1,1,1, 1,1,0,1, 0,0,1,0, 1,0,0,1, 0,1,1,0),
B = c(0,1,1,1, 1,1,0,0, 0,1,1,0, 1,0,0,1, 0,1,1,0, 1,0,0,1),
C = c(1,1,0,0, 1,0,1,0, 1,0,0,1, 0,1,1,1, 1,1,0,0, 0,0,1,1),
D = c(0,0,1,1, 0,1,0,1, 0,1,1,0, 1,1,0,0, 0,0,1,1, 1,1,0,0),
stringsAsFactors = FALSE)
acc <- ena.accumulate.data(
units = rows[, "unit", drop = FALSE], conversation = rows[, "conv", drop = FALSE],
metadata = rows[, c("grp", "score")], codes = rows[, c("A","B","C","D")],
window.size.back = 2)
set <- ena.make.set(acc, dimensions = 2)
Summary
ena.rotate.by.hena.regression_2fails with an error pointing at an unrelated line when the underlying regression is rank-deficient.Severity: low — diagnostics. The underlying situation is legitimate; only the reporting is unhelpful.
Setup (rENA 0.3.1, R 4.4.2)
Reproduce
regression_2fitslm(score ~ V), needingn_edges + 1parameters. With fewer units than that, the fit is rank-deficient and R returnsNAcoefficients:With 7+ units and the same 4 codes it succeeds:
Root cause
norm_v1 <- sqrt(sum(v1 * v1))isNAwhenv1containsNA(aliased coefficients), andif (norm_v1 != 0)(ena.rotate.by.regression.R:61) then errors without explaining that the model was rank-deficient.Suggested fix
Check for
NAcoefficients after the fit and report the rank deficiency directly.What ena-python does
Different, and not obviously better:
numpy.linalg.lstsqreturns the minimum-norm solution for an underdetermined system, so ena-python returns a finite, unit-norm rotation vector where rENA errors. That answer is one of infinitely many, so rENA's loud failure is arguably the safer behavior. Improving ena-python's handling here is tracked as future work.