Since Interest_in_Acme
is unobservable, the average causal effect of Loyalty Club Membership
on Spend
is unidentifiable. However, there is an important exception to that rule, that is if Interest_in_Acme
is perfectly correlated ($r=1.0$ or $r=0.0$) with Spend_in_Prev_Year
. If those two variables are perfectly correlated (i.e. contain the same information), then Spend_in_Prev_Year
can be adjusted for instead and used to identify the average causal effect.
In the much more likely scenario of Interest_in_Acme
being somewhat correlated with Spend_in_Prev_Year
, a somewhat biased estimate of the average causal effect can be obtained. The more that the two are correlated, the less biased the estimate adjusted for Spend_in_Prev_Year
.
A simple simulation study
To demonstrate the concept, below is a simple simulation study (Python 3.5+ code). Let $L$ be Interest_in_Acme
, $L^*$ be Spend_in_Prev_Year
, $A$ be Loyalty Club Membership
, $Y(a)$ be the potential Spend
under treatment plan $a$, and $Y$ be the observed spending. For simplicity, my simulation uses binary variables. To reduce variability to sample size, I set $n=1,000,000$. For the estimator of the average causal effect, I used the standardized mean difference (i.e. g-formula, do-calculus, etc.)
import numpy as np
import pandas as pd
# Simulation parameters
n = 1000000
correlation = 1.0
np.random.seed(20191223)
# Simulating data set
df = pd.DataFrame()
df['L'] = np.random.binomial(n=1, p=0.25, size=n)
df['L*'] = np.random.binomial(n=1, p=correlation*df['L'] + (1-correlation)*(1-df['L']), size=n)
df['A'] = np.random.binomial(1, p=(0.25 + 0.5*df['L']), size=n)
df['Ya0'] = np.random.binomial(1, p=(0.75 - 0.5*df['L']), size=n)
df['Ya1'] = np.random.binomial(1, p=(0.75 - 0.5*df['L'] - 0.1*1 -0.1*1*df['L']), size=n)
df['Y'] = (1-df['A'])*df['Ya0'] + df['A']*df['Ya1']
# True causal effect
print("True Causal Effect:", np.mean(df['Ya1'] - df['Ya0']))
# Standardized Mean Estimator
l1 = np.mean(df['L*'])
l0 = 1 - l1
r1_l0 = np.mean(df.loc[(df['A']==1) & (df['L*']==0)]['Y'])
r1_l1 = np.mean(df.loc[(df['A']==1) & (df['L*']==1)]['Y'])
r0_l0 = np.mean(df.loc[(df['A']==0) & (df['L*']==0)]['Y'])
r0_l1 = np.mean(df.loc[(df['A']==0) & (df['L*']==1)]['Y'])
rd_stdmean = (r1_l0*l0 + r1_l1*l1) - (r0_l0*l0 + r0_l1*l1)
print('Standardized Mean Risk Difference:', rd_stdmean)
Below are the results for some various correlations (you can also run this code and change the correlation
parameter to see the result of the various changes. Note that $r=0.50$ is no correlation
True Average Causal Effect: -0.124
$r=1.0$: -0.123
$r=0.99$: -0.136
$r=0.50$: -0.347
$r=0.05$: -0.180
Summary
As a justification, you may believe that Interest_in_Acme
and Spend_in_Prev_Year
are highly correlated meaning you may be close to the true average causal effect. While you can't fully identify, you may believe that those two variables are highly correlated so your estimate is close to the truth. As a final note, this problem becomes more complicated for continuous variables since functional forms of variables may differ.