econmethods 3.0.5.7__tar.gz → 3.0.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: econmethods
3
- Version: 3.0.5.7
3
+ Version: 3.0.6
4
4
  Summary: A python package implementing various econometrical tests and estimators
5
5
  Home-page: https://github.com/NaturionBG/econmethods
6
6
  Author: NaturionBG
@@ -188,7 +188,7 @@ class CipsTest:
188
188
  pass
189
189
 
190
190
 
191
- class HausmanOneWay:
191
+ class Hausman:
192
192
  '''
193
193
  Implementation of the Hausman procedure to test whether it is more feasible to used random effects against fixed effects.
194
194
  -
@@ -217,73 +217,77 @@ class HausmanOneWay:
217
217
  - Via instance.verdict() prints the verdict of the Hausman test according to the given parameters.
218
218
  '''
219
219
  def __init__(self, data: pd.DataFrame, force_GLS: bool = False, level: int = 5) -> None:
220
- self.__df = data
221
- self.__exog = len(data.columns[3:])
222
- self.__l =[]
223
- self.__fgls = force_GLS
224
- for i in range(1, self.__exog+1):
225
- self.__l.append(f'x{i}')
226
- self.__df.columns = ['SpUnit', 'time', 'target'] + self.__l
227
- self.__alpha = level/100
228
- self.__RE = 'GLS'
229
- self.__T = len(self.__df.time.unique())
230
- self.__N = len(self.__df.SpUnit.unique())
231
-
232
-
220
+ self.__df = data
221
+ self.__exog = len(data.columns[3:])
222
+ self.__l = []
223
+ self.__fgls = force_GLS
224
+ for i in range(1, self.__exog+1):
225
+ self.__l.append(f'x{i}')
226
+ self.__df.columns = ['SpUnit', 'time', 'target'] + self.__l
227
+ self.__alpha = level/100
228
+ self.__RE = 'GLS'
229
+ self.__T = len(self.__df.time.unique())
230
+ self.__N = len(self.__df.SpUnit.unique())
231
+
233
232
  def build_FE(self) -> pd.DataFrame:
234
- fe = self.__df.copy(deep=True)
235
- for i, unit in enumerate(self.__df.SpUnit.unique()):
236
- fe.loc[:, f'd{i}'] = np.where(fe.SpUnit == unit, 1, 0)
237
- return fe.iloc[:, 2:]
238
-
239
- def build_GLS(self, w_err: float) -> pd.DataFrame | None:
240
- re = self.__df.groupby('SpUnit')[self.__df.columns[2:]].mean()
241
- temp1 = sm.OLS(re.iloc[:, 0], sm.add_constant(re.iloc[:, 1:])).fit()
242
- temp2 = sm.OLS(re.iloc[:, 0], re.iloc[:, 1:]).fit()
243
- if temp1.rsquared > temp2.rsquared:
244
- temp = temp1
245
- else:
246
- temp = temp2
247
- sigma2 = temp.ssr / temp.df_resid
248
- sigma_u = sigma2 - w_err/self.__T
249
- if sigma_u <= 0:
250
- sigma_u = 0
251
- elif sigma_u > 0:
252
- if not self.__fgls:
253
- self.__RE = 'REML'
254
- return None
255
- sig = np.full((self.__T, self.__T), sigma_u)
256
- np.fill_diagonal(sig, sigma_u+w_err)
257
- matrix = np.kron(np.eye(self.__N), sig)
258
- return matrix
259
-
260
-
261
-
233
+ fe = self.__df.copy(deep=True)
234
+ for i, unit in enumerate(self.__df.SpUnit.unique()):
235
+ fe.loc[:, f'd{i}'] = np.where(fe.SpUnit == unit, 1, 0)
236
+ return fe.iloc[:, 2:]
237
+
238
+ def build_GLS(self, w_err: float) -> np.ndarray | None:
239
+ re = self.__df.groupby('SpUnit')[self.__df.columns[2:]].mean()
240
+ temp = sm.OLS(re.iloc[:, 0], sm.add_constant(re.iloc[:, 1:])).fit()
241
+ sigma2 = temp.ssr / temp.df_resid
242
+ sigma_u = sigma2 - w_err / self.__T
243
+ if sigma_u <= 0:
244
+ sigma_u = 0
245
+ elif sigma_u > 0:
246
+ if not self.__fgls:
247
+ self.__RE = 'MLE'
248
+ return None
249
+ sig = np.full((self.__T, self.__T), sigma_u)
250
+ np.fill_diagonal(sig, sigma_u + w_err)
251
+ matrix = np.kron(np.eye(self.__N), sig)
252
+ return matrix
253
+
262
254
  def estimate(self) -> float:
263
255
  fe_df = self.build_FE()
264
- Chi = 0
265
256
  fe_res = sm.OLS(fe_df.iloc[:, 0], fe_df.iloc[:, 1:]).fit()
266
257
  matrix = self.build_GLS(fe_res.mse_resid)
267
258
  if matrix is not None:
268
- re_res = sm.GLS(self.__df.iloc[:, 2], sm.add_constant(self.__df.iloc[:, 3:]), matrix).fit()
259
+ re_res = sm.GLS(self.__df.iloc[:, 2], sm.add_constant(self.__df.iloc[:, 3:]), matrix).fit()
269
260
  else:
270
- re_res = sm.MixedLM(self.__df['target'], sm.add_constant(self.__df[self.__l]), groups=self.__df.SpUnit).fit(reml = True, maxiter=100_00)
271
- for b_fe, b_re, var_fe, var_re in zip(fe_res.params[1:], re_res.params[1:], fe_res.bse[1:]**2, re_res.bse[1:]**2):
272
- Chi += (b_fe - b_re)**2 / (var_fe - var_re)
273
-
274
- return Chi
275
-
276
- def verdict(self) -> None:
277
- Chi = self.estimate()
278
- ch2 = sc.chi2(self.__exog)
279
- p = ch2.sf(Chi)
280
- if p < self.__alpha:
281
- print(f'P-Value: {p} < Alpha: {self.__alpha}. \n According to the Hausman test, you should use the FE (Fixed Effects) model. \n RE estimator: {self.__RE}')
261
+ re_res = sm.MixedLM(self.__df['target'], sm.add_constant(self.__df[self.__l]), groups=self.__df.SpUnit).fit(reml=False, maxiter=100_00)
262
+ x_names = self.__l
263
+ fe_params = fe_res.params
264
+ fe_cov = fe_res.cov_params()
265
+ fe_params_x = fe_params[x_names]
266
+ fe_cov_x = fe_cov.loc[x_names, x_names].values
267
+ re_params = re_res.params
268
+ re_cov = re_res.cov_params()
269
+ if 'const' in re_params.index:
270
+ re_params_x = re_params[x_names]
271
+ re_cov_x = re_cov.loc[x_names, x_names].values
282
272
  else:
283
- print(f'P-Value: {p} > Alpha: {self.__alpha}. \n According to the Hausman test, you should use the RE (Random Effects) model. \n RE estimator: {self.__RE}')
284
-
285
- def __del__(self) -> None:
286
- pass
273
+ re_params_x = re_params[x_names]
274
+ re_cov_x = re_cov.loc[x_names, x_names].values
275
+ d = fe_params_x - re_params_x
276
+ V = fe_cov_x - re_cov_x
277
+ try:
278
+ chi2 = d.T @ np.linalg.inv(V) @ d
279
+ except np.linalg.LinAlgError:
280
+ chi2 = d.T @ np.linalg.pinv(V) @ d
281
+ return chi2
282
+
283
+ def verdict(self) -> None:
284
+ Chi = self.estimate()
285
+ ch2 = sc.chi2(self.__exog)
286
+ p = ch2.sf(Chi)
287
+ if p < self.__alpha:
288
+ print(f'P-Value: {p} < Alpha: {self.__alpha}. \n According to the Hausman test, you should use the FE (Fixed Effects) model. \n RE estimator: {self.__RE}')
289
+ else:
290
+ print(f'P-Value: {p} > Alpha: {self.__alpha}. \n According to the Hausman test, you should use the RE (Random Effects) model. \n RE estimator: {self.__RE}')
287
291
 
288
292
  class FECM:
289
293
  '''
@@ -654,7 +658,7 @@ class FECM:
654
658
  def __del__(self) -> None:
655
659
  pass
656
660
 
657
- class CDTwoWay:
661
+ class CDTest:
658
662
  '''
659
663
  Implementation of the CD test to validate/reject cross-sectional dependence.
660
664
  Hypotheses:
@@ -0,0 +1,3 @@
1
+ from .Lib import CipsTest, HausmanOneWay, FECM, CDTwoWay, SlopeHomogeneityF
2
+
3
+ __all__ = ['CipsTest', 'Hausman', 'FECM', 'CDTest', 'SlopeHomogeneityF']
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: econmethods
3
- Version: 3.0.5.7
3
+ Version: 3.0.6
4
4
  Summary: A python package implementing various econometrical tests and estimators
5
5
  Home-page: https://github.com/NaturionBG/econmethods
6
6
  Author: NaturionBG
@@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
5
5
 
6
6
  setup(
7
7
  name = 'econmethods',
8
- version = 'v3.0.5.7',
8
+ version = 'v3.0.6',
9
9
  description='A python package implementing various econometrical tests and estimators',
10
10
  packages = find_packages(),
11
11
  long_description=long_desc,
@@ -1,3 +0,0 @@
1
- from .Lib import CipsTest, HausmanOneWay, FECM, CDTwoWay, SlopeHomogeneityF
2
-
3
- __all__ = ['CipsTest', 'HausmanOneWay', 'FECM', 'CDTwoWay', 'SlopeHomogeneityF']
File without changes
File without changes