Skip to content

Commit b642734

Browse files
authored
Merge pull request #93 from ejolly/dev
Fix divide by 0 error for non-full rank square matrices
2 parents 5ebb0cb + 5506561 commit b642734

File tree

4 files changed

+10
-4
lines changed

4 files changed

+10
-4
lines changed

pymer4/models/Lm.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,10 @@ def fit(
289289
# Cluster corrected dof (num clusters - num coef)
290290
# Differs from stats and statsmodels which do num cluster - 1
291291
# Ref: http://cameron.econ.ucdavis.edu/research/Cameron_Miller_JHR_2015_February.pdf
292-
df = cluster.nunique() - x.shape[1]
292+
df = cluster.nunique() - np.linalg.matrix_rank(x)
293293
else:
294-
df = x.shape[0] - x.shape[1]
294+
# Use dof calculation that accounts for square matrices to avoid 0 division error or pval lookup error
295+
df = x.shape[0] - np.linalg.matrix_rank(x)
295296
if isinstance(weights, str) and wls_dof_correction:
296297
if weight_groups.ngroups != 2:
297298
w = "Welch-Satterthwait DOF correction only supported for 2 groups in the data"
@@ -408,6 +409,7 @@ def fit(
408409
self.rsquared_adj = rsquared_adj(
409410
self.rsquared, len(res), len(res) - x.shape[1], center_tss
410411
)
412+
# self.rsquared_adj = np.nan
411413
half_obs = len(res) / 2.0
412414
ssr = np.dot(res, res.T)
413415
self.logLike = (-np.log(ssr) * half_obs) - (

pymer4/stats.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,9 @@ def rsquared_adj(r, nobs, df_res, has_constant=True):
638638
float: adjusted coefficient of determination
639639
"""
640640

641+
# Skip calculation if Dof is not a positive number to avoid 0 division error or calculating negative R^2 values
642+
if df_res <= 0:
643+
return np.nan
641644
if has_constant:
642645
return 1.0 - (nobs - 1) / df_res * (1.0 - r)
643646
else:

pymer4/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ def _ols(x, y, robust, n_lags, cluster, all_stats=True, resid_only=False, weight
235235
res, X, robust_estimator=robust, n_lags=n_lags, cluster=cluster
236236
)
237237
else:
238-
sigma = np.sqrt(res.T.dot(res) / (X.shape[0] - X.shape[1]))
238+
# Use dof calculation in the denominator that accounts for square matrices to avoid 0 division error
239+
sigma = np.sqrt(res.T.dot(res) / (X.shape[0] - np.linalg.matrix_rank(X)))
239240
se = np.sqrt(np.diag(np.linalg.pinv(np.dot(X.T, X)))) * sigma
240241

241242
t = b / se

pymer4/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""Specifies current version of pymer4 to be used by setup.py and __init__.py
22
"""
33

4-
__version__ = "0.7.7"
4+
__version__ = "0.7.8.dev0"

0 commit comments

Comments
 (0)