npiv-python 0.1.0
Nonparametric IV (NPIV) estimation in Python
Requires Python: >=3.8


# npiv

This is the Python package **npiv** (Nonparametric Instrumental Variables
Estimation and Inference) replicating the R package [npiv](https://github.com/JeffreyRacine/npiv) written by Jeffrey S. Racine
(<racinej@mcmaster.ca>) and co-authored and maintained by Timothy
Christensen (<timothy.christensen@yale.edu>).

## Description

This package implements methods introduced in [Chen, Christensen, and
Kankanala (2024)](https://doi.org/10.1093/restud/rdae025) for estimating
and constructing uniform confidence bands for nonparametric structural
functions using instrumental variables, including data-driven choice of
tuning parameters. It also provides functionality to construct uniform
confidence bands using the method of [Chen and Christensen
(2018)](https://doi.org/10.3982/QE722). All methods in this package
apply to nonparametric regression as a special case.

## Installation

You can install with `pip`.

``` python
!pip install pynpiv
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.signal import savgol_filter
from npiv import npiv
from npiv import plot_npiv
```

## Examples

### Nonparametric instrumental variables estimation

We present a simple example to Engel curve estimation using data from
the British Family Expenditure Survey. We first load the data and sort
on log household expenditure for plotting purposes. We generate a grid
of log expenditure from 4.5 to 6.5 for plotting.

``` python
# === 1. Load and prepare data ===
# Load the Engel (1995) dataset and sort by logexp
engel = pd.read_csv("data/data_engel.csv")
engel = engel.sort_values("logexp").reset_index(drop=True)

y = engel["food"].to_numpy()          # dependent variable
x = engel[["logexp"]].to_numpy()      # endogenous regressor
z = engel[["logwages"]].to_numpy()    # instrument
x_eval = np.linspace(4.5, 6.5, 150).reshape(-1, 1)
```

To nonparametrically regress `Y` on `X` using `W` as an instrument, use
`npiv(Y ~ X | W)` or `npiv(Y, X, W)`. By default, `npiv` uses a
data-driven choice of sieve dimension based on the method of [Chen,
Christensen, and Kankanala
(2024)](https://doi.org/10.1093/restud/rdae025). We include
`X.eval = logexp.eval` since we want to plot over a smaller region than
the support of log expenditure.

``` python  
food_engel = npiv(y, x, z, X_eval = x_eval)
```

We plot the estimated function and 95% uniform confidence bands using
the command `plot`. By default, the confidence bands are generated using
the method of [Chen, Christensen, and Kankanala
(2024)](https://doi.org/10.1093/restud/rdae025). We include
`showdata = True` to overlay the data points.

``` python
plot_npiv(food_engel)
```

![](figures/npiv_base.png)<!-- -->

Confidence bands for the derivative of the structural function are
plotted by including the argument `type = "deriv"`.

``` python
plot_npiv(food_engel, kind = 'deriv')
```

![](figures/npiv_deriv.png)<!-- -->

### Nonparametric regression

We can estimate a conditional mean function by nonparametric regression
with data-driven choice of sieve dimension simply by passing the
regressor as the instrument. The following example estimates the Engel
curve for food by regression of `food` on `logexp`:

``` python
food_engel = npiv(y, x, z, X_eval = x_eval,  knots = "quantiles")
plot_npiv(food_engel)
```

![](figures/npiv_nonpa.png)<!-- -->

The plot is wiggly, indicating that the algorithm has selected a fairly
large sieve dimension. This can sometimes happen when the data are far
from uniform, because the default method uses splines with knots placed
uniformly over the support of the data. We can restore good performance
by including `knots = "quantiles"` to use splines with knots placed at
the quantiles of the data.

``` python
food_engel = npiv(y, x, z, X_eval = x_eval,  knots = "quantiles")
plot_npiv(food_engel)
```

![](figures/npiv_quant.png)<!-- -->