其实我根本就没用过DID,也是第一次听说安慰剂检验,完全Follow的这一篇文章:模型系列-DID入门(附Stata操作)

摘抄一下里面安慰剂检验的部分:

安慰剂检验核心思想即即虚构处理组进行回归。

第一步:选取政策实施之前的年份进行处理,例如,政策发生在2014年,研究区间为2013-2015年。我们可以把研究区间向前移动到2011-2013年,并假定政策实施年份为2012年,然后进行回归。

第二步:选取已知的并不受政策实施影响的群组作为处理组进行回归。

如果不同虚构方式下的DID估计量的回归结果依然显著,说明原来的估计结果很有可能出现了偏误。

此外还可以利用不同不同的对照组进行回归,看研究结论是否依然一致。或者选取一个完全不受政策干预影响的因素作为被解释变量进行回归,如果DID估计量的回归结果依然显著,说明原来的估计结果很有可能出现了偏误。

注:以上如果回归结果显著,说明原结果是一定有问题的,而如果回归结果不显著,并不一定能表明原结果没问题。

好像和叶老师上课讲的差不多。

Python实现(面板数据):

import pandas as pd
from linearmodels import PanelOLS
import numpy as np
from matplotlib import pyplot as plt


def random_treat_and_year(data, year):
    # 随机设定控制组,这个0.3是我随便设定的,可以让我的控制组数量和随机前相比差不多
    arr = np.where(np.random.randn(data['id'].max())>0.3,1,0)
    mapping = lambda x: arr[x-1]
    data['Treatment'] = data['id'].map(mapping)
    mapping = lambda x: 1 if x >= year else 0
    data['Post'] = data['year'].map(mapping)
    data = data.set_index(['id', 'year'])
    data['Treatment_Post'] = data['Treatment'] * data['Post']
    return data

# 返回一次结果的年份、p值、系数、标准差
# 包含固定效应
# y为因变量,X为自变量
def get_a_result(data, year):
    model = PanelOLS(data.y,
            data[X],
            entity_effects=True,
            time_effects=True)
    result = model.fit()
    return {'year': year,
            'pvalue': result.pvalues[0],
            'beta': result.params[0],
            'se': result.std_errors[0]}

# 每个年份随机抽N次
def work(data, start, end, n):
    li = []
    for year in range(start, end):
        for i in range(n):
            data = random_treat_and_year(data, year)
            li.append(get_a_result(data, year))
            data = data.reset_index()
    df = pd.DataFrame(li)
    return df


# 读取数据
data = pd.read_excel('data.xlsx', sheet_name='data')
start = 2010
end = 2018
n = 100
df = work(data, start, end, n)
print(df.groupby('year').mean())

# 简易画图
plt.scatter(df.beta, df.pvalue)
plt.show()