Generalized DeltaDualBounds

Using the delta method, dual bounds can also be used to upper and lower bound estimands of the form

\[\theta = h(E[f(Y(0), Y(1), X)], E[z_1(Y(1), X)], E[z_0(Y(0), X)])\]

where \(h\) is a continuous function that is nondecreasing in its first input, \(f\) is a real-valued function, and \(z_1\) and \(z_0\) are potentially vector-valued functions.

Using the dualbounds.delta.DeltaDualBounds class, one merely has to specify the functions \(h\), \(z_0\), \(z_1\), and \(f\). Then, one can compute dual bounds on these quantities using the same API as the DualBounds class.

For example, the following code shows how to compute dual bounds on the quantity:

\[\theta = \frac{E[\max(Y(1), Y(0))]}{E[Y(0)^2]} + E[Y(1)] \cdot E[X_1].\]
[1]:
# Import packages
import sys; sys.path.insert(0, "../../../")
import numpy as np
import dualbounds as db
from dualbounds.generic import DualBounds

# Synthetic data
data = db.gen_data.gen_regression_data(
    n=500, p=30, dgp_seed=1, sample_seed=1
)
[2]:
# Fit delta dual bounds
delta_db = db.delta.DeltaDualBounds(
    # input arbitrary functions
    h=lambda fval, z1, z0: fval / z0 + z1[0] * z1[1],
    z1=lambda y1, x: np.array([y1, x[0]]),
    z0=lambda y0, x: y0**2,
    f=lambda y0, y1, x: np.maximum(y1, y0),
    # input data
    outcome=data['y'],
    treatment=data['W'],
    covariates=data['X'],
    propensities=data['pis'],
    # outcome model
    outcome_model='ridge',
)
delta_db.fit()
print(delta_db.results().to_markdown())
Cross-fitting the outcome model.
Estimating optimal dual variables.
|            |      Lower |    Upper |
|:-----------|-----------:|---------:|
| Estimate   |  0.263098  | 0.280716 |
| SE         |  0.149856  | 0.151063 |
| Conf. Int. | -0.0306139 | 0.576795 |