EconML icon indicating copy to clipboard operation
EconML copied to clipboard

Individual Treatment Effects

Open PrannoyLFC opened this issue 1 year ago • 2 comments

Hi @kbattocchi ,

I used the following code to calculate the ATE for my panel data (around ~$18).

dml = DynamicDML(model_y=outcome_model, model_t=treatment_model, cv=2, discrete_treatment=True)

dml.fit(Y=Y, T=T, X=None, W=X, groups=groups)

Is it possible to get individual treatment effects too? Ie how much causal impact the treatment would gave in the outcome variable for each row of my data?

PrannoyLFC avatar Apr 01 '24 11:04 PrannoyLFC

@PrannoyLFC I think, in order to get the effect for each row, you need to use dml.effect(x_test)Reference

ellpri avatar Apr 02 '24 08:04 ellpri

Hi!

I was wondering the same thing. The '.effect' method does not seem to be doing what I want. As a consequence, I have come up with this piece of code

`

def calculate_tau(df, model, X_names, T_names):

    m = len(T_names)

    coefficients = [model.coef_[i::m] for i in range(0, m)]
    # coeffcients for each treatment in shape (m, t, P)
    coefficients = np.stack(coefficients, axis=0)

    intercept = [model.intercept_[i::m] for i in range(0, m)]
    # intercept for each treatment in shape (m, t, 1)
    intercept = np.stack(intercept, axis=0)[:, :, np.newaxis]

    # only the first row for heterogeneity
    X = df.loc[:, X_names].head(1).to_numpy()

    # DML estimators assume that the treatment effect is linear in T (assuming there is no treatment featurizer)
    # marginal effect is constant regardless of what values of T you provide
    # If either argument is N-D, N > 2, it is treated as a stack of matrices
    # residing in the last two indexes and broadcast accordingly
    effects = np.add(np.matmul(coefficients, X.T), intercept)
    effects = np.squeeze(effects, axis=2)  # shape (m, t)

    T = df.loc[:, T_names].to_numpy()

    df["tau"] = np.sum(np.multiply(effects.T, T), axis=1)  # shape (t)

    return df

data = data.sort_values(["ID", "time"]).groupby("ID").apply(
    calculate_tau, model=est, X_names=X.columns, T_names=T.columns).reset_index(drop=True)

`

TimCosemans avatar Aug 21 '24 08:08 TimCosemans