Confounding Example: Finding causal effects from observed data

Suppose you are given some data with treatment and outcome. Can you determine whether the treatment causes the outcome, or the correlation is purely due to another common cause?

import os, sys
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
import dowhy
from dowhy import CausalModel
import dowhy.datasets, dowhy.plotter
import logging

Let’s create a mystery dataset for which we need to determine whether there is a causal effect.

Creating the dataset. It is generated from either one of two models: * Model 1: Treatment does cause outcome. * Model 2: Treatment does not cause outcome. All observed correlation is due to a common cause.

rvar = 1 if np.random.uniform() >0.5 else 0
data_dict = dowhy.datasets.xy_dataset(10000, effect=rvar,
df = data_dict['df']
print(df[["Treatment", "Outcome", "w0"]].head())
   Treatment    Outcome        w0
0   4.986545   9.650083 -1.139237
1   6.638307  14.064543  1.051314
2   2.396964   4.321689 -3.710417
3   7.385791  14.558907  1.427228
4   2.781060   6.330348 -2.941221
dowhy.plotter.plot_treatment_outcome(df[data_dict["treatment_name"]], df[data_dict["outcome_name"]],

Using DoWhy to resolve the mystery: Does Treatment cause Outcome?

STEP 1: Model the problem as a causal graph

Initializing the causal model.

model= CausalModel(
WARNING:dowhy.causal_model:Causal Graph not provided. DoWhy will construct a graph based on data inputs.

Showing the causal model stored in the local file “causal_model.png”

from IPython.display import Image, display

STEP 2: Identify causal effect using properties of the formal causal graph

Identify the causal effect using properties of the causal graph.

identified_estimand = model.identify_effect(proceed_when_unidentifiable=True)
WARNING:dowhy.causal_identifier:If this is observed data (not from a randomized experiment), there might always be missing confounders. Causal effect cannot be identified perfectly.
Estimand type: nonparametric-ate

### Estimand : 1
Estimand name: backdoor1 (Default)
Estimand expression:
Estimand assumption 1, Unconfoundedness: If U→{Treatment} and U→Outcome then P(Outcome|Treatment,w0,U) = P(Outcome|Treatment,w0)

### Estimand : 2
Estimand name: iv
No such variable found!

### Estimand : 3
Estimand name: frontdoor
No such variable found!

STEP 3: Estimate the causal effect

Once we have identified the estimand, we can use any statistical method to estimate the causal effect.

Let’s use Linear Regression for simplicity.

estimate = model.estimate_effect(identified_estimand,
print("Causal Estimate is " + str(estimate.value))

# Plot Slope of line between treamtent and outcome =causal effect
dowhy.plotter.plot_causal_effect(estimate, df[data_dict["treatment_name"]], df[data_dict["outcome_name"]])
Causal Estimate is -0.019836578259104343

Checking if the estimate is correct

print("DoWhy estimate is " + str(estimate.value))
print ("Actual true causal effect was {0}".format(rvar))
DoWhy estimate is -0.019836578259104343
Actual true causal effect was 0

Step 4: Refuting the estimate

We can also refute the estimate to check its robustness to assumptions (aka sensitivity analysis, but on steroids).

Adding a random common cause variable

res_random=model.refute_estimate(identified_estimand, estimate, method_name="random_common_cause")
Refute: Add a Random Common Cause
Estimated effect:-0.019836578259104343
New effect:-0.019826671323794898

Replacing treatment with a random (placebo) variable

res_placebo=model.refute_estimate(identified_estimand, estimate,
        method_name="placebo_treatment_refuter", placebo_type="permute")
Refute: Use a Placebo Treatment
Estimated effect:-0.019836578259104343
New effect:3.341207189269113e-06
p value:0.47

Removing a random subset of the data

res_subset=model.refute_estimate(identified_estimand, estimate,
        method_name="data_subset_refuter", subset_fraction=0.9)

Refute: Use a subset of data
Estimated effect:-0.019836578259104343
New effect:-0.019587864980808264
p value:0.47

As you can see, our causal estimator is robust to simple refutations.