statspai.interference¶
interference ¶
Interference and Spillover Effects.
Estimates direct and spillover treatment effects when SUTVA (Stable Unit Treatment Value Assumption) is violated, i.e., one unit's treatment affects another unit's outcome.
References
Hudgens, M. G. & Halloran, M. E. (2008). Toward Causal Inference with Interference. JASA, 103(482), 832-842. [@hudgens2008toward]
Aronow, P. M. & Samii, C. (2017). Estimating Average Causal Effects Under General Interference. Annals of Applied Statistics, 11(4), 1912-1947. [@aronow2017estimating]
SpilloverEstimator ¶
Spillover / interference effects estimator.
NetworkHTEResult
dataclass
¶
Output of :func:network_hte.
InwardOutwardResult
dataclass
¶
Output of :func:inward_outward_spillover.
MatchedPairResult
dataclass
¶
Output of matched-pair cluster RCT estimation.
CrossClusterRCTResult
dataclass
¶
Output of cross-cluster RCT with interference correction.
StaggeredClusterRCTResult
dataclass
¶
Staggered-rollout cluster RCT output.
DNCGNNDiDResult
dataclass
¶
Output of DNC + GNN + DiD.
network_hte ¶
network_hte(data: DataFrame, *, y: str, treatment: str, neighbor_exposure: str, covariates: Sequence[str], n_folds: int = 5, alpha: float = 0.05, random_state: int = 0) -> NetworkHTEResult
Orthogonal learning of direct + spillover effects on networks.
Estimates the partially-linear model
Y_i = alpha(X_i) + tau_d * D_i + tau_s * E_i + eps_i,
E[eps_i | X_i, D_i, E_i] = 0,
where D_i is unit i's own treatment and E_i is a scalar
summary of neighbourhood exposure (e.g. share treated). Uses
Chernozhukov-style double orthogonalisation: cross-fit nuisance
models for E[Y|X], E[D|X] and E[E|X], then regress
residualised Y on residualised (D, E).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
|
required |
y
|
str
|
|
required |
treatment
|
str
|
|
required |
neighbor_exposure
|
str
|
|
required |
covariates
|
sequence of str
|
|
required |
n_folds
|
int
|
|
5
|
alpha
|
float
|
|
0.05
|
random_state
|
int
|
|
0
|
Returns:
| Type | Description |
|---|---|
NetworkHTEResult
|
|
References
Wu & Yuan (arXiv:2509.18484, 2025). [@wu2025estimating]
inward_outward_spillover ¶
inward_outward_spillover(data: DataFrame, *, y: str, treatment: str, inward_exposure: str, outward_exposure: str, covariates: Optional[Sequence[str]] = None, alpha: float = 0.05) -> InwardOutwardResult
Decompose spillover into 'inward' (incoming edges to unit i) and 'outward' (outgoing edges from unit i to neighbours).
The model is
Y_i = alpha + tau*D_i + tau_in * E_in_i + tau_out * E_out_i + X'beta + eps
where E_in_i and E_out_i are user-constructed inward /
outward exposure summaries (e.g. in a directed network: share of
incoming neighbours treated vs. share of outgoing).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
|
required |
y
|
str
|
|
required |
treatment
|
str
|
|
required |
inward_exposure
|
str
|
|
required |
outward_exposure
|
str
|
|
required |
covariates
|
sequence of str
|
|
None
|
alpha
|
float
|
|
0.05
|
Returns:
| Type | Description |
|---|---|
InwardOutwardResult
|
|
References
Fang, Airoldi & Forastiere (arXiv:2506.06615, 2025). [@fang2025inward]
cluster_cross_interference ¶
cluster_cross_interference(data: DataFrame, y: str, cluster: str, treat: str, neighbour_treat_share: str, alpha: float = 0.05) -> CrossClusterRCTResult
Cluster RCT with explicit interference adjustment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
|
required |
y
|
str
|
Individual-level outcome. |
required |
cluster
|
str
|
Cluster identifier. |
required |
treat
|
str
|
Cluster-level binary treatment. |
required |
neighbour_treat_share
|
str
|
Share of treated neighbours per cluster (precomputed by user from spatial / network adjacency). |
required |
alpha
|
float
|
|
0.05
|
Returns:
| Type | Description |
|---|---|
CrossClusterRCTResult
|
|
cluster_staggered_rollout ¶
cluster_staggered_rollout(data: DataFrame, y: str, cluster: str, time: str, first_treat: str, leads: int = 2, lags: int = 4, alpha: float = 0.05) -> StaggeredClusterRCTResult
Staggered-rollout cluster RCT estimator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
Panel: cluster × time × outcome. |
required |
y
|
str
|
first_treat = first calendar time the cluster is treated (0 / NaN for never-treated). |
required |
cluster
|
str
|
first_treat = first calendar time the cluster is treated (0 / NaN for never-treated). |
required |
time
|
str
|
first_treat = first calendar time the cluster is treated (0 / NaN for never-treated). |
required |
first_treat
|
str
|
first_treat = first calendar time the cluster is treated (0 / NaN for never-treated). |
required |
leads
|
int
|
|
2
|
lags
|
int
|
|
2
|
alpha
|
float
|
|
0.05
|
Returns:
| Type | Description |
|---|---|
StaggeredClusterRCTResult
|
|
interference ¶
Unified entry point for the interference / spillover family.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
design
|
str
|
The interference design to estimate under. Supported values are
listed by |
``"partial"``
|
**kwargs
|
Any
|
Passed through unchanged to the target function. |
{}
|
Returns:
| Type | Description |
|---|---|
The underlying estimator's return object. See each underlying
|
|
function's docstring for details.
|
|
Examples:
>>> import statspai as sp
>>> r = sp.interference("partial", data=df, y="y",
... treat="d", cluster="household")
See Also
docs/guides/interference_family.md : the full family guide.
interference_available_designs ¶
Return the full list of registered interference design names.