Skip to content

[upstream rENA 0.3.1] regression_2 errors cryptically on rank-deficient input #4

Description

@HUDongpin

This is an issue in rENA 0.3.1, not in ena-python. It is tracked here because it came out of porting rENA to Python. Reported as an observation, not an accusation — it may be fixed upstream or intended, in which case please correct me. Full write-up: docs/rena-upstream-issues.md

Summary

ena.rotate.by.hena.regression_2 fails 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)
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)

Reproduce

regression_2 fits lm(score ~ V), needing n_edges + 1 parameters. With fewer units than that, the fit is rank-deficient and R returns NA coefficients:

# 6 units, 4 codes -> 6 edges: 7 parameters for 6 observations
ena.rotate.by.hena.regression_2(set, list(x_var = "score ~ V"))
#> Error in if (norm_v1 != 0) { : missing value where TRUE/FALSE needed

With 7+ units and the same 4 codes it succeeds:

units edges params needed result
6 6 7 Error
7 6 7 OK
8 6 7 OK

Root cause

norm_v1 <- sqrt(sum(v1 * v1)) is NA when v1 contains NA (aliased coefficients), and if (norm_v1 != 0) (ena.rotate.by.regression.R:61) then errors without explaining that the model was rank-deficient.

Suggested fix

Check for NA coefficients after the fit and report the rank deficiency directly.

What ena-python does

Different, and not obviously better: numpy.linalg.lstsq returns 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    upstream-renaDefect in rENA (upstream reference implementation), not in pyENA

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions