D
DID 双重差分因果分析
作者:鹿Sir学术研究v1
双重差分(Difference-in-Differences)因果推断分析,自动按样本量选择多元或一元方法,识别行为变化的人口结构驱动因素并给出 p 值显著性检验。适用于政策效果评估、事件影响分析、A/B 测试结果归因等场景。当用户需要做因果推断、政策评估、活动效果归因、前后对比分析时触发。触发词:双重差分、DID、因果分析、政策评估、显著性检验。
下载量
355
点赞
85
价格
免费
技能文档
---
name: did-causal-analysis
title: DID 双重差分因果分析
category: 学术研究
description: 双重差分(Difference-in-Differences)因果推断分析,自动按样本量选择多元或一元方法,识别行为变化的人口结构驱动因素并给出 p 值显著性检验。适用于政策效果评估、事件影响分析、A/B 测试结果归因等场景。当用户需要做因果推断、政策评估、活动效果归因、前后对比分析时触发。触发词:双重差分、DID、因果分析、政策评估、显著性检验。
---
# 双重差分(DiD)因果分析框架
用于因果推断的 DiD 框架,按样本量自动选择方法(多元 vs 一元),核心引擎在 `scripts/did_analysis.py`。
## 方法论
### 集约边际(Intensive Margin)
- **定义**:参与者的行为变化了多少(连续型结果)
- **数据结构**:稀疏数据——只包含实际参与的实体(发生过购买、事件等)
- **结果变量**:连续型(如每个购买者的消费金额)
- **关键点**:不要把未参与实体纳入,也不要构造完整网格——只分析实际参与者
### 广延边际(Extensive Margin)
- **定义**:有多少人改变了行为(0/1 二元结果)
- **数据结构**:完整面板——全部实体 × 全部时期(包含未参与者)
- **结果变量**:二元(0/1 表示是否参与)
- **关键点**:必须包含未参与者才能度量参与率变化
### 回归方法
两种方法均使用 `Y = α + βX + γPost + δ(X × Post) + ε`,其中 δ 即 DiD 估计量。
**多元异质 DiD**
- 一次回归同时估计所有特征
- 控制特征间混杂
- 适用条件:`n ≥ k × min_sample_ratio`(默认至少 1 万样本)
**一元 DiD**
- 每个特征单独回归
- 小样本下更稳健
- 适用条件:样本量不足时使用,或作为兜底
**重要**:两种方法都用 statsmodels 回归提供 p 值,支持统计推断。
## 关键:数据准备要求
### 集约边际——稀疏数据(仅参与者)
正确做法——只聚合实际发生的交易:
```python
# 按实体-时期聚合实际交易
intensive_df = transactions.groupby(['entity_id', 'period'])['value'].sum().reset_index()
# 结果:只有发生过事件的行(如活跃参与者的 3404 行)
```
**原因**:集约边际度量的是「参与者多投入了多少」,不是「未参与者是否开始参与」。给未参与者填 0 会稀释效应、改变研究问题。
### 广延边际——完整面板(全部用户)
正确做法——构造完整的实体 × 分组 × 时期网格:
```python
# 构造全部组合
from itertools import product
all_entities = entities_df['entity_id'].unique()
all_groups = target_groups # 如品类、地区、产品
all_periods = ['baseline', 'treatment']
complete_grid = pd.DataFrame(
list(product(all_entities, all_groups, all_periods)),
columns=['entity_id', 'period']
)
# 标记谁参与了(1)、谁没参与(0)
events_lookup = transactions[['entity_id', 'period']].drop_duplicates()
events_lookup['participated'] = 1
extensive_df = complete_grid.merge(events_lookup, how='left')
extensive_df['participated'] = extensive_df['participated'].fillna(0).astype(int)
# 结果:全部实体 × 分组 × 时期,二元结果变量
```
**原因**:广延边际度量的是「参与率是否上升」,必须同时知道谁参与了、谁没参与。
## API
### 构造参数 `DIDAnalyzer(min_sample_ratio=10, significance_level=0.05, min_group_size=1)`
- `min_sample_ratio=10`:多元 DiD 要求的样本数与特征数之比
- `significance_level=0.05`:p 值阈值,按任务语境取 0.05–0.1
- `min_group_size=1`:一元 DiD 每组最小观测数
### `intensive_margin(df, features, value_col, top_n=None, sort_by='estimate', asc=False)`
分析集约边际:参与者的行为变化了多少。
**输入数据**:稀疏实体-时期数据(仅参与者)
- `df`:稀疏 DataFrame——只含有参与行为的实体
- `features`:人口特征列名列表
- `value_col`:连续结果列(如 `amount`、`spending`)
- `top_n`:取前 N 个特征(None 为全部)
- `sort_by`:`estimate` 或 `p_value`
- `asc`:True 升序 / False 降序
**返回**:`{"feature": str, "did_estimate": float, "p_value": float, "method": str}` 列表
### `extensive_margin(df, features, value_col='purchased', top_n=None, sort_by='estimate', asc=False)`
分析广延边际:有多少人改变了行为。
**输入数据**:完整实体-时期面板(全部实体,含未参与者)
- `df`:完整 DataFrame——全部实体 × 全部时期
- `features`:人口特征列名列表
- `value_col`:二元结果列(0/1),默认 `purchased`
- `top_n` / `sort_by` / `asc`:同上
**返回**:`{"feature": str, "did_estimate": float, "p_value": float, "method": str}` 列表
### 内部方法选择逻辑
- 优先尝试多元异质 DiD(样本量充足时)
- 样本不足时回退到一元 DiD
- 两种方法均通过回归提供 p 值
## 技能工作流
### 步骤1:明确研究问题与边际类型
先确认要度量「参与者投入变化」(集约)还是「参与率变化」(广延),这决定数据准备方式。
### 步骤2:按边际类型准备数据
集约边际→稀疏数据;广延边际→完整面板。参照上文数据准备要求,禁止混用。
### 步骤3:运行分析
```python
from did_analysis import DIDAnalyzer
analyzer = DIDAnalyzer(min_sample_ratio=10, significance_level=0.05)
results = analyzer.intensive_margin(df, features=['age_group', 'region'], value_col='amount')
```
### 步骤4:解读结果
- 按 `did_estimate` 排序识别效应方向与强度
- 按 `p_value` 判断显著性(对照 `significance_level`)
- 报告中注明所用方法(multivariate/univariate)与样本量使用说明
# DID 双重差分因果分析 双重差分因果推断:自动选择多元/一元方法,输出各人口特征的行为变化效应与 p 值显著性。 ## 使用 ```text 用双重差分分析这次活动对不同年龄段用户消费金额的影响 ``` ```text 评估新政策实施前后参与率变化,给出显著性检验结果 ``` ## 工作原理 区分集约边际(参与者投入变化,稀疏数据)与广延边际(参与率变化,完整面板)两条分析路径,统一用 `Y = α + βX + γPost + δ(X × Post) + ε` 回归;样本充足时一次回归估计全部特征并控制混杂,不足时逐特征回退一元方法,均基于 statsmodels 提供 p 值。
支持平台:Qoder · QoderWork · Claude · Codex 等 AI 编程助手