Skip to content

Commit

Permalink
Only include J, F in summary if this makes sense. (#116)
Browse files Browse the repository at this point in the history
* Only include J, F in summary if this makes sense.

* changes.

* Prepare 0.5.0 release.

* Mention docs in changelog.
  • Loading branch information
mlondschien authored Aug 27, 2024
1 parent f993b0a commit 6f80109
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 17 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Changelog
=========

0.5.0 - 2024-0x-xx
0.5.0 - 2024-08-27
------------------

**New features:**
Expand All @@ -21,6 +21,11 @@ Changelog
LIML and TSLS estimators) and the number of instruments is less than the number of
endogenous regressors.

- The :class:`~ivmodels.summary.Summary` now only includes and prints the results of the
J-statistic and (multivariate) F-test for instrument strength if this makes sense.

- The docs have been updated and include examples.

0.4.0 - 2024-08-08
------------------

Expand Down
22 changes: 15 additions & 7 deletions ivmodels/models/kclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,20 @@ def _fuller_alpha(self, kappa):
else:
return 0.0

def _is_iv_estimator(self, kappa=None):
"""Check if the estimator is an IV estimator."""
if kappa is None:
kappa = self.kappa

if isinstance(kappa, str):
fuller_match = re.match(r"fuller(\(\d+\.?\d*\))?", kappa, re.IGNORECASE)
return kappa.lower() in {"tsls", "2sls", "liml"} or fuller_match is not None

# Note that this can be inconsistent, as fuller(1) is an IV estimator, but
# might result in kappa<1, e.g., if k=mx.
elif isinstance(kappa, (float, int)):
return self.kappa >= 1

@staticmethod
def _spectrum(X, y, Z=None, X_proj=None, y_proj=None, subset_by_index=None):
if (y_proj is None or X_proj is None) and Z is None:
Expand Down Expand Up @@ -366,13 +380,7 @@ def fit(self, X, y, Z=None, C=None, *args, **kwargs):
n, k = Z.shape
mx, mc = X.shape[1], C.shape[1]

if (
(
isinstance(self.kappa, str)
and self.kappa.lower() in {"tsls", "2sls", "liml"}
)
or (isinstance(self.kappa, (int, float)) and self.kappa >= 1)
) and k < mx:
if self._is_iv_estimator() and k < mx:
raise ValueError(
f"Need at least as many instruments (got {k}) as endogenous regressors "
f"(got {mx})."
Expand Down
27 changes: 19 additions & 8 deletions ivmodels/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,18 @@ def fit(self, X, y, Z=None, C=None, *args, **kwargs):
self.statistic_, self.p_value_ = test_(
Z=Z, X=X, y=y, C=C, beta=np.zeros(X.shape[1]), fit_intercept=fit_intercept
)
self.f_statistic_, self.f_p_value_ = tests.rank_test(
Z, X, C=C, fit_intercept=fit_intercept
)
self.j_statistic_, self.j_p_value_ = tests.j_test(
Z, X, y=y, C=C, fit_intercept=fit_intercept
)

self.f_statistic_, self.f_p_value_ = (
tests.rank_test(Z, X, C=C, fit_intercept=fit_intercept)
if self.kclass._is_iv_estimator()
else None
), None

self.j_statistic_, self.j_p_value_ = (
tests.j_test(Z, X, y=y, C=C, fit_intercept=fit_intercept)
if self.kclass._is_iv_estimator() and Z.shape[1] > X.shape[1]
else None
), None

return self

Expand All @@ -213,9 +219,14 @@ def __format__(self, format_spec: str) -> str: # noqa D

string += f"""
Endogenous model statistic: {self.statistic_:{format_spec}}, p-value: {_format_p_value(self.p_value_, format_spec)}
(Multivariate) F-statistic: {self.f_statistic_:{format_spec}}, p-value: {_format_p_value(self.f_p_value_, format_spec)}
Endogenous model statistic: {self.statistic_:{format_spec}}, p-value: {_format_p_value(self.p_value_, format_spec)}"""
if self.f_statistic_ is not None and self.f_p_value_ is not None:
string += f"""
(Multivariate) F-statistic: {self.f_statistic_:{format_spec}}, p-value: {_format_p_value(self.f_p_value_, format_spec)}"""
if self.j_statistic_ is not None and self.j_p_value_ is not None:
string += f"""
J-statistic (LIML): {self.j_statistic_:{format_spec}}, p-value: {_format_p_value(self.j_p_value_, format_spec)}"""

return string

def __str__(self): # noqa D
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ requires = ['setuptools', 'setuptools-scm', 'wheel']
name = "ivmodels"
description = "IV Models"
readme = "README.md"
version = "0.4.0"
version = "0.5.0"
requires-python = ">=3.7"
authors = [
{ name = "Malte Londschien", email = "[email protected]" },
Expand Down

0 comments on commit 6f80109

Please sign in to comment.