Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 26 additions & 21 deletions tests/test_vs_fixest.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,10 +933,8 @@ def test_glm_vs_fixest(N, seed, dropna, fml, inference, family):
("Y~ csw0(X2, f3) + X2"),
("Y~ X1 + csw0(X2, f3) + X2"),
("Y ~ X1 + csw0(f1, f2) | f3"),
("Y ~ X1 | csw0(f1,f2)"),
("Y ~ X1 + sw(X2, f1, f2)"),
("Y ~ csw(X1, X2, f3)"),
# ("Y ~ X2 + csw0(, X2, X2)"),
("Y ~ sw(X1, X2) | csw0(f1,f2,f3)"),
("Y ~ C(f2):X2 + sw0(X1, f3)"),
("Y + Y2 ~X1"),
Expand All @@ -955,6 +953,10 @@ def test_glm_vs_fixest(N, seed, dropna, fml, inference, family):
("Y + Y2 ~ X1 | csw0(f1,f2)"),
("Y + log(Y2) ~ sw(X1, X2) | csw0(f1,f2,f3)"),
("Y ~ C(f2):X2 + sw0(X1, f3)"),
# Known discrepancy: R fixest counts the intercept as an additional parameter for FE models in sw/sw0/csw0/mvsw
# TODO: enable tests once https://github.com/lrberge/fixest/issues/631 is resolved/clarified
# ("Y ~ X2 + csw0(, X2, X2)"),
# ("Y ~ X1 | csw0(f1,f2)"),
# ("Y ~ i(f1,X2) | csw0(f2)"),
# ("Y ~ i(f1,X2) | sw0(f2)"),
# ("Y ~ i(f1,X2) | csw(f2, f3)"),
Expand Down Expand Up @@ -994,23 +996,24 @@ def test_multi_fit(N, seed, beta_type, error_type, dropna, fml_multi):
ssc=fixest.ssc(True, "nonnested", False, True, "min", "min"),
)

for x in range(0):
n_models = len(pyfixest.all_fitted_models)

for x in range(n_models):
mod = pyfixest.fetch_model(x)
py_coef = mod.coef().values
py_se = mod.se().values

# sort py_coef, py_se
py_coef, py_se = (np.sort(x) for x in [py_coef, py_se])
# skip models with no estimated coefficients (e.g., intercept-only FE models)
if len(py_coef) == 0:
continue

fixest_object = r_fixest.rx2(x + 1)
fixest_coef = fixest_object.rx2("coefficients")
fixest_se = fixest_object.rx2("se")

# fixest_coef = stats.coef(r_fixest)
# fixest_se = fixest.se(r_fixest)
fixest_coef = np.atleast_1d(np.array(fixest_object.rx2("coefficients")))
fixest_se = np.atleast_1d(np.array(fixest_object.rx2("se")))

# sort fixest_coef, fixest_se
fixest_coef, fixest_se = (np.sort(x) for x in [fixest_coef, fixest_se])
# sort for order-independent comparison
py_coef, py_se = np.sort(py_coef), np.sort(py_se)
fixest_coef, fixest_se = np.sort(fixest_coef), np.sort(fixest_se)

np.testing.assert_allclose(
py_coef, fixest_coef, rtol=rtol, atol=atol, err_msg="Coefs are not equal."
Expand Down Expand Up @@ -1068,23 +1071,25 @@ def test_split_fit(N, seed, beta_type, error_type, dropna, fml_multi, split, fsp
**({"fsplit": ro.Formula("~" + fsplit)} if fsplit is not None else {}),
)

# TODO: split/fsplit has known sample-handling differences vs R fixest
# that cause large coefficient mismatches (not just SE scaling).
# This needs a separate fix. See gh#1161.
for x in range(0):
mod = pyfixest.fetch_model(x)
py_coef = mod.coef().values
py_se = mod.se().values

# sort py_coef, py_se
py_coef, py_se = (np.sort(x) for x in [py_coef, py_se])
# skip models with no estimated coefficients (e.g., intercept-only FE models)
if len(py_coef) == 0:
continue

fixest_object = r_fixest.rx2(x + 1)
fixest_coef = fixest_object.rx2("coefficients")
fixest_se = fixest_object.rx2("se")

# fixest_coef = stats.coef(r_fixest)
# fixest_se = fixest.se(r_fixest)
fixest_coef = np.atleast_1d(np.array(fixest_object.rx2("coefficients")))
fixest_se = np.atleast_1d(np.array(fixest_object.rx2("se")))

# sort fixest_coef, fixest_se
fixest_coef, fixest_se = (np.sort(x) for x in [fixest_coef, fixest_se])
# sort for order-independent comparison
py_coef, py_se = np.sort(py_coef), np.sort(py_se)
fixest_coef, fixest_se = np.sort(fixest_coef), np.sort(fixest_se)

np.testing.assert_allclose(
py_coef, fixest_coef, rtol=rtol, atol=atol, err_msg="Coefs are not equal."
Expand Down
Loading