4  Continuous Workflows

Continuous-treatment workflows are where the package’s design becomes most visible: instead of asking for a single treated-vs-control contrast, you ask for a whole response curve.

4.1 The Core Workflow

flowchart LR
  A["Observed data: X, t, y"] --> B["Fit estimator"]
  B --> C["Build treatment grid"]
  C --> D["Predict on the grid"]
  D --> E["Plot ADRF or compare to truth"]

4.2 Step 1: Build A Grid

import numpy as np
import polars as pl

grid = pl.DataFrame(
    {"t0": np.linspace(float(t["t0"].min()), float(t["t0"].max()), X.height)}
)

The grid can have any row count: predict(t) returns one average response per requested treatment row and averages over the covariate sample stored during fit.

4.3 Step 2: Predict A Curve

from skcausal.causal_estimators import DirectRegressor
from sklearn.linear_model import LinearRegression

estimator = DirectRegressor(outcome_regressor=LinearRegression())
estimator.fit(X, t, y)
curve = estimator.predict(grid)

For a direct method, the returned curve is the average of \hat{E}[Y | X, T=t] over the observed covariate sample.

4.4 Step 3: Compare Methods Carefully

The docs examples pair DirectRegressor with GPS, but the important point is not that one is “regression” and one is “weighting”. The important point is that they use different nuisance-model structure to target the same ADRF.

Tip

Use the continuous treatments example when you want the short version, and the SyntheticDataset2 walkthrough when you want a fuller benchmark with multiple estimators.

4.5 The Main Habit To Keep

When a continuous-treatment result looks surprising, check three things before trusting the curve:

  1. Whether the requested treatment grid stays inside the observed treatment support.
  2. Whether the estimator returns a response curve or a density-like score.
  3. Whether the observed association is clearly confounded relative to the synthetic truth or domain knowledge.