Fit an instrumental-variables (2SLS) regression with a weak-instrument diagnostic.
Endogenous regressors are instrumented with excluded instruments while exog (included exogenous controls) and feffects (absorbed fixed effects) enter directly. The fit delegates to pyfixest’s native IV estimator, and the result carries the first-stage F statistic — the conventional check for weak instruments (a value below about 10 is the Staiger-Stock warning sign). For panel data, prefer :func:analyze_panel_iv_regression, which manages the entity/time fixed effects for you.
Excluded instrument name(s). At least as many instruments as endogenous regressors are required (the order condition); more instruments over-identify the model.
model (the fitted pyfixest IV model), etable (rendered table), df (tidy coefficient frame), the endog / instruments / exog names, and first_stage_f / first_stage_p (the first-stage weak-instrument F and p-value).
If the dependent variable is non-numeric (only OLS-family IV is supported).
Examples
The canonical Acemoglu-Johnson-Robinson (2001) example: instrument average protection against expropriation risk with log settler mortality, on the 64-country base sample. The instrumented slope is the famous ≈ 0.94:
This IV (2SLS) regression instruments **expropriation_risk** with *log_settler_mortality*, relating it to **log_gdp_pc_1995**. Two-stage least squares isolates the part of the endogenous regressor that moves with the instruments, purging the endogeneity that biases ordinary least squares.
- **expropriation_risk** (instrumented): a one-unit increase is associated with log_gdp_pc_1995 that is 0.944 higher (statistically significant at the 1% level).
The first-stage F is 22.9 — **above** the conventional weak-instrument threshold of 10, so the instruments are reasonably strong.
IV is trustworthy only when the instruments are both **relevant** (a strong first stage) and **excludable** — related to log_gdp_pc_1995 solely through the instrumented regressor.
_These are associations, not causal effects. A causal reading needs a research design — see `explain('correlation_vs_causation')`._