statspai.dose_response¶
dose_response ¶
Continuous Treatment Effects: Dose-Response Estimation.
Estimates the dose-response function E[Y(t)] for continuous treatments using the generalized propensity score (GPS) approach and kernel-based methods.
References
Hirano, K. & Imbens, G. W. (2004). The Propensity Score with Continuous Treatments. Applied Bayesian Modeling and Causal Inference from Incomplete-Data Perspectives, 226164, 73-84. [@hirano2004propensity]
Kennedy, E. H., Ma, Z., McHugh, M. D., & Small, D. S. (2017). Non-parametric methods for doubly robust estimation of continuous treatment effects. JRSS-B, 79(4), 1229-1245. [@kennedy2017parametric]
DoseResponse ¶
Generalized Propensity Score dose-response estimator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
|
required |
y
|
str
|
|
required |
treat
|
str
|
|
required |
covariates
|
list of str
|
|
required |
n_dose_points
|
int
|
|
20
|
dose_range
|
tuple
|
|
None
|
treatment_model
|
sklearn estimator
|
|
None
|
outcome_model
|
sklearn estimator
|
|
None
|
n_bootstrap
|
int
|
|
200
|
alpha
|
float
|
|
0.05
|
random_state
|
int
|
|
42
|
Examples:
>>> import numpy as np
>>> import pandas as pd
>>> import statspai as sp
>>> rng = np.random.default_rng(0)
>>> n = 150
>>> age = rng.normal(50, 10, n)
>>> weight = rng.normal(70, 12, n)
>>> dosage = 0.5 * age + 0.3 * weight + rng.normal(0, 5, n)
>>> outcome = 0.8 * dosage + 0.2 * age + rng.normal(0, 3, n)
>>> df = pd.DataFrame({"outcome": outcome, "dosage": dosage,
... "age": age, "weight": weight})
>>> est = sp.DoseResponse(df, y="outcome", treat="dosage",
... covariates=["age", "weight"],
... n_dose_points=6, n_bootstrap=8, random_state=0)
>>> res = est.fit()
>>> isinstance(res, sp.CausalResult)
True
>>> list(res.detail.columns)
['dose', 'response', 'se', 'ci_lower', 'ci_upper', 'marginal_effect']
References
[@hirano2004propensity], [@kennedy2017parametric]
VCNetResult
dataclass
¶
Bases: ResultProtocolMixin
Dose-response curve returned by :func:vcnet / :func:scigan.
Attributes:
| Name | Type | Description |
|---|---|---|
t_grid |
ndarray
|
Treatment grid at which the curve is evaluated. |
mu_hat |
ndarray
|
Estimated dose-response :math: |
se |
ndarray
|
Bootstrap pointwise standard errors. |
ci_lo, ci_hi |
ndarray
|
Pointwise lower / upper confidence band. |
coef_matrix |
ndarray
|
Varying-coefficient matrix of shape |
n_obs, n_basis |
int
|
|
detail |
dict
|
|
Examples:
>>> import statspai as sp
>>> import numpy as np
>>> import pandas as pd
>>> df = pd.DataFrame({
... "y": np.random.randn(200),
... "dose": np.random.rand(200),
... "x1": np.random.randn(200),
... })
>>> res = sp.vcnet(df, y="y", treatment="dose",
... covariates=["x1"])
>>> res.mu_hat[:3] # dose-response on the t-grid
>>> print(res.summary()) # tidy curve table
dose_response ¶
dose_response(data: DataFrame, y: str, treat: str, covariates: List[str], n_dose_points: int = 20, dose_range: Optional[Tuple[float, float]] = None, treatment_model: Optional[BaseEstimator] = None, outcome_model: Optional[BaseEstimator] = None, n_bootstrap: int = 200, alpha: float = 0.05, random_state: int = 42) -> CausalResult
Estimate the dose-response function for a continuous treatment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
Input data. |
required |
y
|
str
|
Outcome variable. |
required |
treat
|
str
|
Continuous treatment variable. |
required |
covariates
|
list of str
|
Covariate names. |
required |
n_dose_points
|
int
|
Number of dose levels to evaluate. |
20
|
dose_range
|
tuple of (float, float)
|
(min, max) dose range. If None, uses 5th-95th percentile. |
None
|
treatment_model
|
sklearn estimator
|
Model for E[T|X]. Default: GBM. |
None
|
outcome_model
|
sklearn estimator
|
Model for E[Y|T, GPS]. Default: GBM. |
None
|
n_bootstrap
|
int
|
Bootstrap iterations for confidence bands. |
200
|
alpha
|
float
|
Significance level. |
0.05
|
random_state
|
int
|
|
42
|
Returns:
| Type | Description |
|---|---|
CausalResult
|
detail contains the dose-response curve: columns 'dose', 'response', 'se', 'ci_lower', 'ci_upper'. model_info contains 'avg_marginal_effect' (derivative). |
Examples:
>>> import statspai as sp, numpy as np, pandas as pd
>>> rng = np.random.default_rng(0)
>>> n = 400
>>> age = rng.normal(40, 10, n)
>>> weight = rng.normal(70, 12, n)
>>> dosage = 0.5 * age + rng.normal(0, 5, n) # confounded dose
>>> outcome = 0.2 * dosage + 0.1 * weight + rng.normal(0, 1, n)
>>> df = pd.DataFrame({"outcome": outcome, "dosage": dosage,
... "age": age, "weight": weight})
>>> result = sp.dose_response(df, y="outcome", treat="dosage",
... covariates=["age", "weight"])
>>> result.detail # dose-response curve
scigan ¶
scigan(data: DataFrame, y: str, treatment: str, covariates: Sequence[str], t_grid: Optional[Sequence[float]] = None, propensity_weights: Optional[ndarray] = None, **kwargs: Any) -> VCNetResult
Adversarial dose-response estimator (Bica et al. 2020).
The reference SCIGAN architecture is a GAN — too heavy to ship as
a dependency-free algorithm. This entry point exposes a
propensity-weighted VCNet fit that captures the essential
"balancing" behaviour of SCIGAN: residual imbalance along the
treatment axis is re-weighted using a user-provided propensity_weights
(g(T | X)^{-1}). For the full SCIGAN training loop, plug in
your own GAN-generated counterfactual samples and pass the
re-weighting through propensity_weights.
Examples:
>>> import statspai as sp
>>> import numpy as np
>>> import pandas as pd
>>> df = pd.DataFrame({
... "y": np.random.randn(200),
... "dose": np.random.rand(200),
... "x1": np.random.randn(200),
... })
>>> w = np.ones(len(df)) # inverse-propensity balancing weights
>>> res = sp.scigan(df, y="y", treatment="dose",
... covariates=["x1"],
... propensity_weights=w)
>>> res.mu_hat[:3] # balanced dose-response curve