Repository navigation
BUG: Raise a clear error when a panel model has no residual degrees o… - #799
Merged
Merged
Conversation
…f freedom A model with as many parameters as observations once the effects are removed raised "ZeroDivisionError: division by zero" when the covariance was scaled by n / (n - k), and when the F-statistics were computed. The panels are small, but they are what is left of a panel after the missing values, the singletons and the absorbed effects are dropped: PooledOLS with 2 observations, a constant and a regressor, PanelOLS with entity or time effects for 2 entities with 2 periods and 2 regressors, BetweenOLS with 2 entities, a constant and a regressor, FirstDifferenceOLS with 1 entity of 3 periods and 2 regressors, and FamaMacBeth with a cross-section that has as many entities as regressors. The covariance now raises a ValueError that says that the model has no residual degrees of freedom, and how many observations, regressors and degrees of freedom of the effects it has. With debiased=False the estimates and the covariance are defined, the model F-statistic is an InvalidTestStatistic, and the summary can be printed. The pooled F-statistic of PanelOLS, which tests that the effects are zero, is an InapplicableTestStatistic if the effects do not use any degrees of freedom (a single entity or a single period with a constant, where the effect is the constant) and an InvalidTestStatistic if there are no residual degrees of freedom. The models with residual degrees of freedom do not change. The tests estimate each of the models with each covariance estimator, with and without debiased, and compare the slopes of the model with a single entity with the slopes of the pooled regression with a constant.
…integer BetweenOLS regresses the means of the entities. Regressors that are not collinear in the data can be collinear in the means: there can be fewer entities than regressors, and the dummy variables of the periods of a balanced panel all have the mean 1/T for every entity, so that they are collinear with the constant. The rank check of the model looks at the data, and the fit returned a minimum norm solution that is not an estimate of the parameters. The error came later, as numpy's "LinAlgError: Singular matrix" when the standard errors were used, and it did not say what was wrong. fit now checks the rank of the regression of the means, as the models check the rank of the data, and raises a ValueError that says that the regressors are collinear in the means of the entities, when it happens, and that check_rank=False skips the check. The other covariance estimators and the weights are not affected, and neither are the models that have the rank. The df_model of the results was the tuple (k,) and not the integer k that the other models return. The tests use a panel with more regressors than entities and the wage panel with the dummy variables of the years, which are the two cases, and check that the same models without the dummy variables are estimated with the degrees of freedom N - k.
…entity or period PanelOLS with entity_effects=True and time_effects=True for a panel that has a single entity (or a single period) raised pandas' "ValueError: No objects to concatenate". The two effects are removed by demeaning the data in the dimension with more groups, and then in the other dimension using the dummy variables of the dimension with fewer groups. With one entity or one period there are no dummy variables to remove, and concatenating the empty list failed. The data that have been demeaned in the first dimension are now returned when there are no dummy variables. The effects absorb all of the variation of the regressors, as they do for entity effects alone and a single entity, and the model raises the AbsorbingEffectError that says so, for each of the algorithms (the default, LSDV through use_lsdv, and low_memory). The tests check the error for panels of 1 entity and of 1 period, and that demeaning both dimensions of such a panel gives zeros.
generate_panel_data(rng=numpy.random.default_rng(0)) raised "AttributeError: 'Generator' object has no attribute 'randint'". The function draws the categories of the effects and of the clusters with randint, which only a RandomState has, and the documentation only said RandomState. Generators are what NumPy recommends, and what the rest of the package and its tests use, so the function now draws the integers with integers for a Generator and with randint for a RandomState. The other draws (standard_normal, chisquare and choice) are methods of both. Calls with a RandomState, or without rng, give the same data as before. The existing test of the function listed random states as a parameter but never passed them to the function. It does now, with a Generator added, and a new test checks that a seed gives the same data, the ranges of the categories, and the values that a RandomState gives (taken from the function before the change).
…nel_data The clusters of generate_panel_data were the concatenation, along the rows, of a frame with the first cluster variable and of a frame with both cluster variables. The result had twice as many rows as the data, with an index that is not unique, and half of the rows had a missing value of the second variable. Clustered covariances need one row of clusters for each observation, and the frame could not be used with the data that the function returns. The clusters are now the frame with both variables, varcat.0 and varcat.1, for the observations of the data. The first variable is the one that the removed frame had, so that the values are those that a RandomState gives for the second half of the old frame, and the draws of the other variables are unchanged. The tests check the shape, the index, the missing values, the columns, the range of the values, that the clusters of an entity are the same in all of its periods, the values for a seeded RandomState (the values of the old frame), and that the clusters work in a clustered covariance of PanelOLS.
…arnings The two warnings of FamaMacBeth about the regressions that cannot be estimated called them "time-series regressions" (and "time-series observation available to estimate cross-sectional regressions"). The model estimates one cross-sectional regression for each period, and then uses the time series of the estimates. The warnings now say how many cross-sectional regressions cannot be estimated due to deficient rank, and how many can be estimated when there are fewer than there are parameters, which is when inference is not available. The tests check the texts of the warnings.
With check_rank=False the panel models skip the computation of the rank of exog and use the number of columns, which is the rank if the regressors are not collinear. They used self.exog.shape[1], and the shape of the PanelData is (variables, periods, entities), so that the rank was the number of periods. The rank is used to decide if the regressors contain a constant that is not a column, because the regressors with a constant have the rank of the regressors alone. The wrong rank gave the wrong answer: * Two dummy variables that add to one, in a panel with 5 periods, were not a constant. The R-squared of PooledOLS was uncentered, 0.2942 instead of 0.1877, that of BetweenOLS 0.5137 instead of 0.0709, and the F-statistics tested the model as if it had no constant. * Three regressors without a constant, in a panel with 2 periods, were a constant. The R-squared of PooledOLS was -0.8760 instead of 0.0304 and FirstDifferenceOLS raised "Constants are not allowed in first difference regressions". The models whose regressors have a constant column, which is found before the rank is used, and the default check_rank=True do not change. The tests compare the models with check_rank=False with those with check_rank=True, and the R-squared of PooledOLS with the R-squared written out in NumPy, for both panels.
… not checked test_formulas_rank_check fits each model with check_rank=False to regressors that are not full rank, and FirstDifferenceOLS passed only because the rank that the models used when the rank was not checked was the number of periods of the panel and not the number of regressors. The function that looks for a constant that is not a column reads regressors that are not full rank as containing an implicit constant, and first differences do not allow a constant. With the number of regressors as the rank, FirstDifferenceOLS raises "Constants are not allowed in first difference regressions." for such regressors, as it does when the rank is computed. The test now expects the error for that model. The other models do not change: the regressors with check_rank=False are estimated as before.
The panel models check that the weights are strictly positive, once the observations with missing weights have been dropped, and then scale them to have a mean of one. An infinite weight passed the check, and the scaling made it NaN and every other weight zero. The models then failed with errors from NumPy, SciPy and pandas that do not say what is wrong: "array must not contain infs or NaNs", "SVD did not converge", an AbsorbingEffectError for entity effects, and "operands could not be broadcast together with shapes (278,1) (280,2)" for FirstDifferenceOLS. The weights have to be finite as well as strictly positive, and the models raise "weights must be strictly positive and finite." for zero, negative and infinite weights. Missing weights are dropped with their observations, as before. The tests check the error of every model for -inf, inf, 0 and -1, and that missing weights give the model of the data without those observations.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #799 +/- ##
==========================================
+ Coverage 99.60% 99.62% +0.02%
==========================================
Files 136 144 +8
Lines 26057 28302 +2245
Branches 1873 1983 +110
==========================================
+ Hits 25954 28196 +2242
- Misses 38 41 +3
Partials 65 65
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…f freedom
A model with as many parameters as observations once the effects are removed raised
"ZeroDivisionError: division by zero" when the covariance was scaled by n / (n - k),
and when the F-statistics were computed. The panels are small, but they are what is
left of a panel after the missing values, the singletons and the absorbed effects are
dropped: PooledOLS with 2 observations, a constant and a regressor, PanelOLS with
entity or time effects for 2 entities with 2 periods and 2 regressors, BetweenOLS with
2 entities, a constant and a regressor, FirstDifferenceOLS with 1 entity of 3 periods
and 2 regressors, and FamaMacBeth with a cross-section that has as many entities as
regressors.
The covariance now raises a ValueError that says that the model has no residual degrees
of freedom, and how many observations, regressors and degrees of freedom of the effects
it has. With debiased=False the estimates and the covariance are defined, the model
F-statistic is an InvalidTestStatistic, and the summary can be printed. The pooled
F-statistic of PanelOLS, which tests that the effects are zero, is an
InapplicableTestStatistic if the effects do not use any degrees of freedom (a single
entity or a single period with a constant, where the effect is the constant) and an
InvalidTestStatistic if there are no residual degrees of freedom. The models with
residual degrees of freedom do not change.
The tests estimate each of the models with each covariance estimator, with and without
debiased, and compare the slopes of the model with a single entity with the slopes of
the pooled regression with a constant.