Skip to content

Commit 6f80109

Browse files
authored
Only include J, F in summary if this makes sense. (#116)
* Only include J, F in summary if this makes sense. * changes. * Prepare 0.5.0 release. * Mention docs in changelog.
1 parent f993b0a commit 6f80109

File tree

4 files changed

+41
-17
lines changed

4 files changed

+41
-17
lines changed

CHANGELOG.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Changelog
22
=========
33

4-
0.5.0 - 2024-0x-xx
4+
0.5.0 - 2024-08-27
55
------------------
66

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

24+
- The :class:`~ivmodels.summary.Summary` now only includes and prints the results of the
25+
J-statistic and (multivariate) F-test for instrument strength if this makes sense.
26+
27+
- The docs have been updated and include examples.
28+
2429
0.4.0 - 2024-08-08
2530
------------------
2631

ivmodels/models/kclass.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,20 @@ def _fuller_alpha(self, kappa):
257257
else:
258258
return 0.0
259259

260+
def _is_iv_estimator(self, kappa=None):
261+
"""Check if the estimator is an IV estimator."""
262+
if kappa is None:
263+
kappa = self.kappa
264+
265+
if isinstance(kappa, str):
266+
fuller_match = re.match(r"fuller(\(\d+\.?\d*\))?", kappa, re.IGNORECASE)
267+
return kappa.lower() in {"tsls", "2sls", "liml"} or fuller_match is not None
268+
269+
# Note that this can be inconsistent, as fuller(1) is an IV estimator, but
270+
# might result in kappa<1, e.g., if k=mx.
271+
elif isinstance(kappa, (float, int)):
272+
return self.kappa >= 1
273+
260274
@staticmethod
261275
def _spectrum(X, y, Z=None, X_proj=None, y_proj=None, subset_by_index=None):
262276
if (y_proj is None or X_proj is None) and Z is None:
@@ -366,13 +380,7 @@ def fit(self, X, y, Z=None, C=None, *args, **kwargs):
366380
n, k = Z.shape
367381
mx, mc = X.shape[1], C.shape[1]
368382

369-
if (
370-
(
371-
isinstance(self.kappa, str)
372-
and self.kappa.lower() in {"tsls", "2sls", "liml"}
373-
)
374-
or (isinstance(self.kappa, (int, float)) and self.kappa >= 1)
375-
) and k < mx:
383+
if self._is_iv_estimator() and k < mx:
376384
raise ValueError(
377385
f"Need at least as many instruments (got {k}) as endogenous regressors "
378386
f"(got {mx})."

ivmodels/summary.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,18 @@ def fit(self, X, y, Z=None, C=None, *args, **kwargs):
195195
self.statistic_, self.p_value_ = test_(
196196
Z=Z, X=X, y=y, C=C, beta=np.zeros(X.shape[1]), fit_intercept=fit_intercept
197197
)
198-
self.f_statistic_, self.f_p_value_ = tests.rank_test(
199-
Z, X, C=C, fit_intercept=fit_intercept
200-
)
201-
self.j_statistic_, self.j_p_value_ = tests.j_test(
202-
Z, X, y=y, C=C, fit_intercept=fit_intercept
203-
)
198+
199+
self.f_statistic_, self.f_p_value_ = (
200+
tests.rank_test(Z, X, C=C, fit_intercept=fit_intercept)
201+
if self.kclass._is_iv_estimator()
202+
else None
203+
), None
204+
205+
self.j_statistic_, self.j_p_value_ = (
206+
tests.j_test(Z, X, y=y, C=C, fit_intercept=fit_intercept)
207+
if self.kclass._is_iv_estimator() and Z.shape[1] > X.shape[1]
208+
else None
209+
), None
204210

205211
return self
206212

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

214220
string += f"""
215221
216-
Endogenous model statistic: {self.statistic_:{format_spec}}, p-value: {_format_p_value(self.p_value_, format_spec)}
217-
(Multivariate) F-statistic: {self.f_statistic_:{format_spec}}, p-value: {_format_p_value(self.f_p_value_, format_spec)}
222+
Endogenous model statistic: {self.statistic_:{format_spec}}, p-value: {_format_p_value(self.p_value_, format_spec)}"""
223+
if self.f_statistic_ is not None and self.f_p_value_ is not None:
224+
string += f"""
225+
(Multivariate) F-statistic: {self.f_statistic_:{format_spec}}, p-value: {_format_p_value(self.f_p_value_, format_spec)}"""
226+
if self.j_statistic_ is not None and self.j_p_value_ is not None:
227+
string += f"""
218228
J-statistic (LIML): {self.j_statistic_:{format_spec}}, p-value: {_format_p_value(self.j_p_value_, format_spec)}"""
229+
219230
return string
220231

221232
def __str__(self): # noqa D

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ requires = ['setuptools', 'setuptools-scm', 'wheel']
55
name = "ivmodels"
66
description = "IV Models"
77
readme = "README.md"
8-
version = "0.4.0"
8+
version = "0.5.0"
99
requires-python = ">=3.7"
1010
authors = [
1111
{ name = "Malte Londschien", email = "malte@londschien.ch" },

0 commit comments

Comments
 (0)