Skip to content

BUG: Validate the method of AbsorbingLS.fit - #783

Merged
bashtage merged 6 commits into
mainfrom
lm71-fix-absorbing-validation
Oct 12, 2026
Merged

bashtage merged 6 commits into
mainfrom
lm71-fix-absorbing-validation

Conversation

@bashtage

Copy link
Copy Markdown
Owner

AbsorbingLS.fit used LSMR for every name of a method other than "auto" and "hdfe".
A misspelled name such as "hdfee", any other name such as "foo", and "HDFE" (which
is a natural way to write the name) were accepted without an error or a warning and
absorbed the variables using LSMR, which the user had not asked for. The method is
now one of "auto", "hdfe" and "lsmr", whatever the case. Any other value, including
a value that is not a string, raises a ValueError that names the accepted values and
the value that was passed. The name is compared in lower case, so a call with "HDFE"
after a call with "hdfe" does not absorb the variables again.

AbsorbingLS.fit used LSMR for every name of a method other than "auto" and "hdfe".
A misspelled name such as "hdfee", any other name such as "foo", and "HDFE" (which
is a natural way to write the name) were accepted without an error or a warning and
absorbed the variables using LSMR, which the user had not asked for. The method is
now one of "auto", "hdfe" and "lsmr", whatever the case. Any other value, including
a value that is not a string, raises a ValueError that names the accepted values and
the value that was passed. The name is compared in lower case, so a call with "HDFE"
after a call with "hdfe" does not absorb the variables again.
The FutureWarning of AbsorbingLS.fit(lsmr_options=...) said "Use absorb_options".
For a model that can be absorbed using HDFE, which is a model without weights whose
absorbed variables are all categorical, absorb_options are the options of HDFE
unless the method is LSMR, so that advice raises a ValueError (#752 made the options
of LSMR with HDFE an error). The warning and the deprecation note in the docstring
now say to use absorb_options with method="lsmr", which gives the same results as
lsmr_options and does not warn.
…bservations

Interaction.drop is public. It removes observations from the instance in place,
but nobs kept the number of observations before the call, so an Interaction that
had dropped 3 of 50 observations reported 50 although its cat, cont and sparse
had 47 rows. AbsorbingLS drops the rows with missing values of its own copies of
the interactions in the same way, and so the interactions of a model with missing
values reported the number of observations before the rows were dropped. nobs is
now the number of observations that remain. drop has a docstring that says that it
modifies the instance in place and returns None, and nobs has one too.
The error that clusters have the wrong number of rows is shared by the IV models,
AbsorbingLS and the panel covariance estimators. It told users that "the model
property `notnull` contains the locations of the observations that have no missing
values". The IV models have notnull, but AbsorbingLS has neither notnull nor isnull,
and the panel models name the property not_null. The message also said "have have".

The message now says what is true of every model: observations with a missing value in
the regression variables are dropped when the model is created, so clusters must have
one row for each of the remaining observations, and the observations with missing
values should be dropped from the data and from clusters before the model is
estimated. This is the smaller change. Giving AbsorbingLS a documented notnull and
isnull, like the IV models, would still leave the panel models without a property of
that name. The first sentence, which the tests match, is unchanged.
The ValueError of IVLIML.fit when kappa cannot be estimated said "This is most
likely occurs if the instrument matrix is rank deficient". It now says "This most
likely occurs if the instrument matrix is rank deficient". The error of the
computation of kappa that follows it is unchanged.
…a period

The numpydoc lint of the documentation conventions requires it.
import pytest

from linearmodels.iv import IV2SLS, IVLIML
import linearmodels.iv.absorbing
@codecov

codecov Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.92473% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.60%. Comparing base (121d869) to head (53a69ea).
⚠️ Report is 57 commits behind head on main.

Files with missing lines Patch % Lines
linearmodels/tests/iv/test_absorbing_validation.py 98.88% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main     #783    +/-   ##
========================================
  Coverage   99.60%   99.60%            
========================================
  Files         127      129     +2     
  Lines       23832    24619   +787     
  Branches     1783     1826    +43     
========================================
+ Hits        23737    24521   +784     
- Misses         35       36     +1     
- Partials       60       62     +2     
Flag Coverage Δ
adder 99.58% <98.92%> (-0.01%) ⬇️
subtractor 99.58% <98.92%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bashtage
bashtage merged commit 00e8c68 into main Oct 12, 2026
23 of 24 checks passed
@bashtage
bashtage deleted the lm71-fix-absorbing-validation branch October 12, 2026 18:56
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.

2 participants