moderndid.npiv_est#

moderndid.npiv_est(y, x, w, x_eval=None, basis='tensor', j_x_degree=3, j_x_segments=None, k_w_degree=4, k_w_segments=None, knots='uniform', deriv_index=1, deriv_order=1, check_is_fullrank=False, w_min=None, w_max=None, x_min=None, x_max=None, data_driven=False)[source]#

Core sieve TSLS estimation for the nonparametric IV model.

Computational backend for npiv that constructs B-spline bases for \(X\) and \(W\), estimates the sieve coefficient vector \(\hat{c}_J\) by two-stage least squares, and evaluates the function estimate \(\hat{h}_J\) and its derivatives at the requested points.

Parameters:
ynumpy.ndarray of shape (n,)

Outcome variable.

xnumpy.ndarray of shape (n,) or (n, p_x)

Endogenous regressors.

wnumpy.ndarray of shape (n,) or (n, p_w)

Instrumental variables.

x_evalnumpy.ndarray of shape (m, p_x), optional

Evaluation points for \(\hat{h}\). If None, uses x.

basis{“tensor”, “additive”, “glp”}, default=”tensor”

Multivariate basis construction for \(X\).

j_x_degreeint, default=3

Degree of B-spline basis for \(X\).

j_x_segmentsint, optional

Number of segments for \(X\) basis. If None, chosen automatically.

k_w_degreeint, default=4

Degree of B-spline basis for \(W\).

k_w_segmentsint, optional

Number of segments for \(W\) basis. If None, chosen automatically.

knots{“uniform”, “quantiles”}, default=”uniform”

Knot placement method.

deriv_indexint, default=1

Which component of \(X\) to differentiate (1-based).

deriv_orderint, default=1

Order of derivative to compute.

check_is_fullrankbool, default=False

Verify full column rank of basis matrices before estimation.

w_min, w_maxfloat, optional

Override support bounds for \(W\).

x_min, x_maxfloat, optional

Override support bounds for \(X\).

Returns:
NPIVResult

Named tuple containing estimation results.

See also

npiv

Public API with data-driven selection and confidence bands.

Examples

Estimate the Engel curve without confidence bands using the core TSLS estimator. This is the computational backend that npiv calls internally:

In [1]: import numpy as np
   ...: from moderndid import load_engel
   ...: from moderndid.npiv import npiv_est
   ...: 
   ...: df = load_engel()
   ...: y = df["food"].to_numpy()
   ...: x = df["logexp"].to_numpy().reshape(-1, 1)
   ...: w = df["logwages"].to_numpy().reshape(-1, 1)
   ...: result = npiv_est(y=y, x=x, w=w, j_x_segments=5)
   ...: print(f"Estimates at {len(result.h)} points")
   ...: print(f"h[:5] = {result.h[:5]}")
   ...: print(f"Pointwise SE[:5] = {result.asy_se[:5]}")
   ...: 
Estimates at 1655 points
h[:5] = [ 9.2505101   0.85939871 -0.26872492 -0.51409879 -0.58251832]
Pointwise SE[:5] = [8.74224844 0.68114868 0.86166929 0.97453574 0.87327581]

Evaluate the estimate on a uniform grid of 50 points:

In [2]: x_grid = np.linspace(x.min(), x.max(), 50).reshape(-1, 1)
   ...: result = npiv_est(y=y, x=x, w=w, x_eval=x_grid, j_x_segments=5)
   ...: print(f"Grid estimates: {len(result.h)} points")
   ...: print(f"h[:5] = {result.h[:5]}")
   ...: 
Grid estimates: 50 points
h[:5] = [9.2505101  6.3173775  4.01575049 2.27296758 1.01636727]