Skip to content

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.

fit

fit() -> CausalResult

Estimate direct and spillover effects.

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

interference(design: str = 'partial', /, **kwargs: Any) -> Any

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 sp.interference_available_designs().

``"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

interference_available_designs() -> list[str]

Return the full list of registered interference design names.