引言:理解倾向值匹配在因果推断中的关键作用

倾向值匹配(Propensity Score Matching, PSM)是现代统计学和计量经济学中解决样本选择偏差的核心技术。当我们想要研究某个处理(如参加培训、接受新药治疗、使用特定教育方法)对结果的影响时,最理想的方式是进行随机对照试验(RCT)。然而,在现实世界中,随机分配往往不可行、不道德或成本过高。这时,观察性研究成为主要替代方案,但观察性研究中普遍存在样本选择偏差——即处理组和对照组在基线特征上存在系统性差异。

倾向值匹配通过将多维协变量压缩为一个一维的倾向值(即个体接受处理的概率),然后基于这个分数进行匹配,从而在观察性研究中模拟随机试验的平衡性。这种方法不仅能有效减少选择偏差,还能提高因果推断的可靠性。本文将提供一个从理论到实践的完整学习路径,帮助你系统掌握倾向值匹配,并理解它如何解决样本选择偏差与因果推断难题。

第一部分:理论基础——理解因果推断与样本选择偏差

1.1 因果推断的基本框架:从相关到因果

在深入倾向值匹配之前,必须先理解因果推断的基本框架。相关性不等于因果性,这是统计学的基本原则。例如,冰淇淋销量和溺水事件高度相关,但显然不是冰淇淋导致溺水,而是夏季高温这个混杂因素同时影响了两者。因果推断的目标是识别和估计处理变量(Treatment)对结果变量(Outcome)的因果效应。

潜在结果框架(Potential Outcomes Framework)是因果推断的理论基石,由鲁宾(Rubin)在1970年代提出。该框架定义了每个个体的潜在结果:如果接受处理,结果为Y(1);如果未接受处理,结果为Y(0)。个体处理效应(ITE)定义为Y(1) - Y(0),但这个值永远无法同时观测到(因为一个个体不能同时处于处理和未处理状态)。因此,我们通常关注平均处理效应(ATE),即E[Y(1) - Y(0)],或处理组的平均处理效应(ATT),即E[Y(1) - Y(0) | D=1],其中D=1表示接受处理。

1.2 样本选择偏差的本质与危害

样本选择偏差(Sample Selection Bias)是指处理组和对照组在可观测和不可观测特征上存在系统性差异,导致直接比较两组结果会产生误导性结论。例如,在研究大学教育对收入的影响时,上大学的人(处理组)可能本来就更聪明、更有动力或家庭背景更好,这些因素既影响上大学的决定,也直接影响收入。如果直接比较大学毕业生和非毕业生的平均收入,会高估教育的回报,因为差异部分来自能力而非教育本身。

样本选择偏差的数学表达是:E[Y(0) | D=1] ≠ E[Y(0) | D=0],即处理组的反事实结果(如果没上大学的收入)与对照组的实际结果不同。这种偏差使得简单比较两组均值无法得到无偏的因果效应估计。

1.3 倾向值匹配的理论原理

倾向值(Propensity Score)定义为给定协变量X条件下个体接受处理的条件概率:e(X) = P(D=1 | X)。罗森鲍姆和鲁宾(Rosenbaum & Rubin, 1983)证明了关键定理:在给定倾向值e(X)的条件下,协变量X在处理组和对照组之间是平衡的,即X ⊥ D | e(X)。这意味着,如果我们基于倾向值进行匹配,就能消除协变量分布差异带来的偏差。

倾向值匹配的核心思想是:找到处理组中每个个体在对照组中倾向值相近的个体,形成”伪随机”的配对。这样,匹配后的处理组和对照组在协变量上近似平衡,类似于随机试验的结果。这种方法特别适用于高维协变量情况,因为将多维协变量压缩为一维倾向值,避免了”维度诅咒”问题。

第二部分:倾向值匹配的完整实施步骤

2.1 第一步:协变量选择与倾向值估计

实施倾向值匹配的第一步是选择合适的协变量。协变量应包括所有可能同时影响处理分配和结果的变量(即混杂因素)。理论上,应包括所有”后门路径”上的变量。实践中,通常基于领域知识和因果图来确定。

倾向值估计通常使用Logistic回归,因为处理变量D是二元变量。模型形式为: $\(P(D=1 | X) = \frac{1}{1 + e^{-(\beta_0 + \beta_1 X_1 + ... + \beta_k X_k)}}\)$

代码示例:使用Python的statsmodels库估计倾向值

import pandas as pd
import numpy as np
import statsmodels.api as sm
from sklearn.neighbors import NearestNeighbors
import matplotlib.pyplot as plt

# 创建模拟数据:研究大学教育对收入的影响
np.random.seed(42)
n = 10000

# 生成协变量
ability = np.random.normal(100, 15, n)  # 能力分数
family_income = np.random.lognormal(10, 0.5, n)  # 家庭收入
motivation = np.random.beta(2, 5, n)  # 动机水平

# 生成处理变量(上大学):受协变量影响
logit = (-5 + 0.05*ability + 0.0001*family_income + 2*motivation)
prob = 1 / (1 + np.exp(-logit))
college = np.random.binomial(1, prob, n)

# 生成结果变量(收入):受教育、能力和家庭收入影响
true_education_effect = 15000  # 真实教育回报
income = 30000 + true_education_effect*college + 200*ability + 0.5*family_income + np.random.normal(0, 5000, n)

# 创建DataFrame
df = pd.DataFrame({
    'ability': ability,
    'family_income': family_income,
    'motivation': motivation,
    'college': college,
    'income': income
})

# 估计倾向值
X = df[['ability', 'family_income', 'motivation']]
X = sm.add_constant(X)  # 添加截距项
y = df['college']

# 使用Logistic回归
logit_model = sm.Logit(y, X)
result = logit_model.fit(disp=0)
print("Logistic回归结果:")
print(result.summary())

# 计算倾向值
df['propensity_score'] = result.predict(X)
print("\n倾向值统计描述:")
print(df['propensity_score'].describe())

上述代码首先生成了一个模拟数据集,其中上大学的决定受能力、家庭收入和动机影响,而收入受教育、能力和家庭收入影响。这模拟了现实中的选择偏差:能力强、家庭收入高的人更可能上大学,而这些特征也直接影响收入。然后使用Logistic回归估计倾向值,输出包括系数估计和倾向值的统计描述。

2.2 第二步:匹配方法选择与实施

估计倾向值后,下一步是进行匹配。常见的匹配方法包括:

  1. 最近邻匹配(Nearest Neighbor Matching):为每个处理组个体在对照组中寻找倾向值最接近的个体。可以是一对一匹配,也可以是多对一匹配。
  2. 卡尺匹配(Caliper Matching):在最近邻匹配基础上,只匹配倾向值差异小于特定阈值(卡尺)的个体,避免”强行匹配”差异过大的样本。
  3. 半径匹配(Radius Matching):为每个处理组个体匹配所有倾向值在特定半径内的对照组个体。
  4. 核匹配(Kernel Matching):使用核函数加权所有对照组个体,权重取决于倾向值距离。

代码示例:使用Python实现最近邻匹配和卡尺匹配

from sklearn.neighbors import NearestNeighbors
import numpy as np

def propensity_score_matching(df, treatment_col='college', propensity_col='propensity_score', 
                              caliper=None, k=1):
    """
    实现倾向值匹配
    :param df: 包含处理变量和倾向值的DataFrame
    :param treatment_col: 处理变量列名
    :param propensity_col: 倾向值列名
    :param caliper: 卡尺大小(可选)
    :param k: 每个处理组样本匹配的对照组样本数
    :return: 匹配后的DataFrame
    """
    # 分离处理组和对照组
    treated = df[df[treatment_col] == 1]
    control = df[df[treatment_col] == 0]
    
    # 准备匹配数据
    treated_ps = treated[propensity_col].values.reshape(-1, 1)
    control_ps = control[propensity_col].values.reshape(-1, 1)
    
    # 使用最近邻算法
    nn = NearestNeighbors(n_neighbors=k, metric='euclidean')
    nn.fit(control_ps)
    
    # 查找每个处理组样本的最近邻
    distances, indices = nn.kneighbors(treated_ps)
    
    # 如果设置了卡尺,过滤掉距离过大的匹配
    if caliper is not None:
        mask = distances.flatten() <= caliper
        treated_indices = np.where(mask)[0]
        control_indices = indices.flatten()[mask]
    else:
        treated_indices = np.arange(len(treated))
        control_indices = indices.flatten()
    
    # 创建匹配后的数据集
    matched_treated = treated.iloc[treated_indices]
    matched_control = control.iloc[control_indices]
    
    # 添加匹配标识
    matched_treated['matched'] = 1
    matched_control['matched'] = 0
    
    # 合并匹配样本
    matched_data = pd.concat([matched_treated, matched_control])
    
    return matched_data

# 执行最近邻匹配(一对一)
matched_nn = propensity_score_matching(df, caliper=None, k=1)
print(f"最近邻匹配后样本量:处理组 {len(matched_nn[matched_nn['college']==1])},对照组 {len(matched_nn[matched_nn['college']==0])}")

# 执行卡尺匹配(卡尺=0.05)
matched_caliper = propensity_score_matching(df, caliper=0.05, k=1)
print(f"卡尺匹配后样本量:处理组 {len(matched_caliper[matched_caliper['college']==1])},对照组 {len(matched_caliper[_matched_caliper['college']==0])}")

# 计算匹配前后的协变量平衡
def calculate_balance(df, vars_list, treatment_col='college'):
    """计算协变量平衡统计量"""
    treated = df[df[treatment_col] == 1]
    control = df[df[treatment_col] == 0]
    
    balance_stats = {}
    for var in vars_list:
        mean_treated = treated[var].mean()
        mean_control = control[var].mean()
        std_diff = (mean_treated - mean_control) / np.sqrt((treated[var].var() + control[var].var()) / 2)
        balance_stats[var] = {
            'treated_mean': mean_treated,
            'control_mean': mean_control,
            'std_diff': std_diff
        }
    return balance_stats

# 比较匹配前后的平衡性
vars_to_check = ['ability', 'family_income', 'motivation']
print("\n匹配前的协变量平衡:")
balance_before = calculate_balance(df, vars_to_check)
for var, stats in balance_before.items():
    print(f"{var}: 处理组均值={stats['treated_mean']:.2f}, 对照组均值={stats['control_mean']:.2f}, 标准化差异={stats['std_diff']:.3f}")

print("\n卡尺匹配后的协变量平衡:")
balance_after = calculate_balance(matched_caliper, vars_to_check)
for var, stats in balance_after.items():
    print(f"{var}: 处理组均值={stats['treated_mean']:.2f}, 对照组均值={stats['control_mean']:.2f}, 标准化差异={stats['std_diff']:.3f}")

这段代码实现了最近邻匹配和卡尺匹配,并计算了匹配前后的协变量平衡。标准化差异(Standardized Difference)是衡量平衡性的关键指标,通常认为小于0.1表示良好平衡。输出会显示匹配后处理组和对照组的协变量均值差异显著缩小,验证了匹配的有效性。

2.3 第三步:平衡性诊断与匹配质量评估

匹配后必须进行平衡性诊断,确保处理组和对照组在协变量上达到良好平衡。常用的诊断方法包括:

  1. 标准化差异(Standardized Mean Difference, SMD):计算两组均值差异除以合并标准差,绝对值小于0.1通常认为可接受。
  2. 方差比(Variance Ratio):检查协变量方差是否平衡,理想值为1。
  3. 可视化:绘制倾向值分布图、协变量分布图(直方图、箱线图)和QQ图。
  4. 统计检验:虽然统计检验(如t检验)不推荐作为平衡性判断的唯一标准(因为大样本下小差异也可能显著),但可作为辅助参考。

代码示例:使用Python进行平衡性诊断可视化

import matplotlib.pyplot as plt
import seaborn as sns

def plot_balance_diagnostic(df_before, df_after, var, treatment_col='college'):
    """绘制协变量平衡诊断图"""
    fig, axes = plt.subplots(1, 3, figsize=(15, 4))
    
    # 1. 匹配前后的分布对比
    treated_before = df_before[df_before[treatment_col] == 1][var]
    control_before = df_before[df_before[treatment_col] == 0][var]
    treated_after = df_after[df_after[treatment_col] == 1][var]
    control_after = df_after[df_after[treatment_col] == 0][var]
    
    axes[0].hist(treated_before, alpha=0.5, label='Treated (Before)', bins=30, density=True)
    axes[0].hist(control_before, alpha=0.5, label='Control (Before)', bins=30, density=True)
    axes[0].set_title(f'{var} - Before Matching')
    axes[0].legend()
    
    axes[1].hist(treated_after, alpha=0.5, label='Treated (After)', bins=30, density=True)
    axes[1].hist(control_after, alpha=0.5, label='Control (After)', bins=30, density=True)
    axes[1].set_title(f'{var} - After Matching')
    axes[1].legend()
    
    # 2. 倾向值分布重叠图
    ps_treated_before = df_before[df_before[treatment_col] == 1]['propensity_score']
    ps_control_before = df_before[df_before[treatment_col] == 0]['propensity_score']
    ps_treated_after = df_after[df_after[treatment_col] == 1]['propensity_score']
    ps_control_after = df_after[df_after[treatment_col] == 0]['propensity_score']
    
    axes[2].hist(ps_treated_before, alpha=0.5, label='Treated (Before)', bins=30, density=True, color='red')
    axes[2].hist(ps_control_before, alpha=0.5, label='Control (Before)', bins=30, density=True, color='blue')
    axes[2].hist(ps_treated_after, alpha=0.5, label='Treated (After)', bins=30, density=True, color='darkred')
    axes[2].hist(ps_control_after, alpha=0.5, label='Control (After)', bins=30, density=True, color='darkblue')
    axes[2].set_title('Propensity Score Distribution')
    axes[2].legend()
    
    plt.tight_layout()
    plt.show()

# 绘制能力变量的平衡诊断图
plot_balance_diagnostic(df, matched_caliper, 'ability')

# 创建平衡性汇总表
def create_balance_table(df_before, df_after, vars_list, treatment_col='college'):
    """创建平衡性汇总表格"""
    balance_data = []
    for var in vars_list:
        # 匹配前
        stats_before = calculate_balance(df_before, [var], treatment_col)[var]
        # 匹配后
        stats_after = calculate_balance(df_after, [var], treatment_col)[var]
        
        balance_data.append({
            'Variable': var,
            'Mean_Treated_Before': stats_before['treated_mean'],
            'Mean_Control_Before': stats_before['control_mean'],
            'SMD_Before': stats_before['std_diff'],
            'Mean_Treated_After': stats_after['treated_mean'],
            'Mean_Control_After': stats_after['control_mean'],
            'SMD_After': stats_after['std_diff']
        })
    
    return pd.DataFrame(balance_data)

balance_table = create_balance_table(df, matched_caliper, vars_to_check)
print("\n平衡性汇总表:")
print(balance_table.round(4))

这段代码生成三个关键图表:匹配前后协变量分布对比、倾向值分布重叠图。倾向值分布图应显示处理组和对照组的分布有大量重叠,这是匹配可行的前提。平衡性汇总表会清晰展示每个协变量在匹配前后的标准化差异变化,通常匹配后SMD应显著降低。

2.4 第四步:估计处理效应

完成匹配并验证平衡性后,最后一步是估计处理效应。对于匹配后的样本,可以直接比较处理组和对照组的均值差异。对于ATT,计算公式为: $\(ATT = \frac{1}{N_T} \sum_{i \in T} (Y_i - \hat{Y}_{i, control})\)\( 其中\)NT\(是处理组样本数,\)\hat{Y}{i, control}$是匹配的对照组个体的结果值。

代码示例:计算处理效应并进行统计推断

def estimate_ate_att(df_matched, outcome_col='income', treatment_col='college'):
    """
    估计平均处理效应(ATE)和处理组平均处理效应(ATT)
    """
    treated = df_matched[df_matched[treatment_col] == 1]
    control = df_matched[df_matched[treatment_col] == 0]
    
    # 简单ATT估计(匹配后直接比较)
    att_simple = treated[outcome_col].mean() - control[outcome_col].mean()
    
    # 使用配对样本估计ATT(更精确)
    # 假设df_matched已经按匹配对排序,这里简化为直接比较
    # 实际中应使用匹配对进行差分
    att_paired = np.mean(treated[outcome_col].values - control[outcome_col].values)
    
    # 计算ATE(如果匹配样本代表总体)
    ate = att_simple
    
    # 计算标准误(使用配对差分法)
    differences = treated[outcome_col].values - control[outcome_col].values
    se_att = np.std(differences) / np.sqrt(len(differences))
    
    # 95%置信区间
    ci_lower = att_paired - 1.96 * se_att
    ci_upper = att_paired + 1.96 * se_att
    
    # t统计量和p值
    t_stat = att_paired / se_att
    p_value = 2 * (1 - stats.t.cdf(abs(t_stat), df=len(differences)-1))
    
    results = {
        'ATT': att_paired,
        'SE': se_att,
        'CI_95': (ci_lower, ci_upper),
        't_stat': t_stat,
        'p_value': p_value,
        'N_treated': len(treated),
        'N_control': len(control)
    }
    
    return results

# 估计处理效应
from scipy import stats

att_results = estimate_ate_att(matched_caliper)
print("\n处理效应估计结果:")
print(f"ATT估计值: {att_results['ATT']:.2f}")
print(f"标准误: {att_results['SE']:.2f}")
print(f"95%置信区间: [{att_results['CI_95'][0]:.2f}, {att_results['CI_95'][1]:.2f}]")
print(f"t统计量: {att_results['t_stat']:.2f}")
print(f"p值: {att_results['p_value']:.4f}")
print(f"样本量 - 处理组: {att_results['N_treated']}, 对照组: {att_results['N_control']}")

# 与真实值比较(模拟数据中已知真实效应)
true_effect = 15000
print(f"\n真实ATT: {true_effect:.2f}")
print(f"估计偏差: {att_results['ATT'] - true_effect:.2f}")

这段代码计算了匹配后的ATT估计值、标准误、置信区间和p值。在模拟数据中,我们可以将估计值与真实值(15000)比较,评估匹配的准确性。通常,良好的匹配应使估计偏差较小。

第三部分:高级主题与常见问题

3.1 倾向值估计模型的选择与优化

虽然Logistic回归是最常用的倾向值估计方法,但其他机器学习模型也可用于提高预测精度,如随机森林、梯度提升树(XGBoost)等。然而,需要注意的是,倾向值估计的目标是平衡协变量,而非单纯预测准确性。过拟合的倾向值模型可能导致协变量平衡不佳。

代码示例:使用随机森林估计倾向值

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

# 使用随机森林估计倾向值
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(df[['ability', 'family_income', 'motivation']], df['college'])

# 获取倾向值预测概率
df['propensity_score_rf'] = rf.predict_proba(df[['ability', 'family_income', 'motivation']])[:, 1]

# 比较Logistic回归和随机森林的平衡性
matched_rf = propensity_score_matching(df, propensity_col='propensity_score_rf', caliper=0.05)
balance_rf = calculate_balance(matched_rf, vars_to_check)

print("\n随机森林倾向值匹配后的平衡性:")
for var, stats in balance_rf.items():
    print(f"{var}: SMD = {stats['std_diff']:.3f}")

# 交叉验证评估模型性能(可选,但需注意目标不是预测)
cv_scores = cross_val_score(rf, df[['ability', 'family_income', 'motivation']], df['college'], cv=5)
print(f"\n随机森林交叉验证AUC: {cv_scores.mean():.3f} (+/- {cv_scores.std():.3f})")

随机森林可能提供更灵活的倾向值估计,但需谨慎使用以避免过拟合。建议在倾向值模型中使用交叉验证,并优先考虑平衡性而非预测精度。

3.2 双重稳健估计与匹配的结合

倾向值匹配假设倾向值模型正确设定,如果模型有误,估计仍可能有偏。双重稳健估计(Doubly Robust Estimation)结合了倾向值模型和结果回归模型,只要其中一个模型正确,就能得到无偏估计。可以将匹配后的结果与结果回归调整结合。

代码示例:双重稳健估计

# 结果回归模型(线性回归)
import statsmodels.formula.api as smf

# 在匹配后的样本上拟合结果模型
matched_data = matched_caliper.copy()
matched_data['residual'] = matched_data['income'] - matched_data['income'].mean()

# 拟合处理组的结果模型
model_treated = smf.ols('income ~ ability + family_income', data=matched_data[matched_data['college']==1]).fit()
# 拟合对照组的结果模型
model_control = smf.ols('income ~ ability + family_income', data=matched_data[matched_data['college']==0]).fit()

# 双重稳健ATT估计
# 1. 使用倾向值加权
treated = matched_data[matched_data['college']==1]
control = matched_data[matched_data['college']==0]

# 计算每个样本的预测结果
treated['pred_outcome'] = model_treated.predict(treated)
control['pred_outcome'] = model_control.predict(control)

# 双重稳健ATT = 处理组实际结果 - 对照组预测结果(在倾向值加权下)
# 这里简化为匹配后的差分,实际中可更复杂
dr_att = np.mean(treated['income'] - control['pred_outcome'])

print(f"双重稳健ATT估计: {dr_att:.2f}")

双重稳健估计提供了额外的保险,但计算更复杂。在实践中,倾向值匹配通常已足够,但了解双重稳健方法有助于处理模型不确定性。

3.3 常见陷阱与解决方案

  1. 共同支持域问题:倾向值分布重叠不足会导致匹配困难。解决方案:检查倾向值分布,删除倾向值极端值(如倾向值<0.1或>0.9的样本)。
  2. 隐藏偏差:即使可观测协变量平衡,不可观测混杂因素仍可能导致偏差。解决方案:进行敏感性分析,评估隐藏偏差需要多大才能改变结论。
  3. 匹配后样本代表性:匹配可能改变样本分布,影响外部有效性。解决方案:报告匹配样本特征,谨慎推广结论。
  4. 小样本问题:小样本下匹配可能不稳定。解决方案:使用多对一匹配或卡尺匹配增加样本量。

第四部分:完整学习路径与资源推荐

4.1 理论学习阶段(1-2个月)

核心教材

  • 《基本无害的计量经济学》(Mostly Harmless Econometrics)by Angrist & Pischke:第2章详细讨论匹配方法,语言通俗易懂。
  • 《因果推断:方法与实践》(Causal Inference: The Mixtape)by Scott Cunningham:第3章专注倾向值匹配,包含大量Stata代码示例。
  • 《倾向值匹配与因果推断》(Propensity Score Matching and Causal Inference)by Guo & Fraser:系统性教材,理论深度足够。

在线课程

  • Coursera的”因果推断”专项课程(由宾夕法尼亚大学提供)
  • edX的”计量经济学”课程(MIT提供)

4.2 实践操作阶段(2-3个月)

软件工具

  • Python:使用statsmodelssklearncausalml
  • R:使用MatchItMatchingtwang
  • Stata:使用psmatch2teffects psmatch命令

实践项目

  1. 使用公开数据集(如NHANES、PSID)复制经典研究
  2. 在Kaggle上寻找因果推断相关竞赛
  3. 自己设计研究问题,收集数据并应用PSM

代码练习

  • 从简单模拟数据开始,逐步增加复杂度
  • 实现自定义匹配算法
  • 编写平衡性诊断函数

4.3 高级进阶阶段(持续学习)

前沿技术

  • 机器学习倾向值估计:使用Lasso、随机森林等
  • 匹配与回归的结合:匹配后回归、双重稳健估计
  • 多处理变量:多值处理的倾向值方法
  • 纵向数据:面板数据的倾向值匹配

学术论文

  • 阅读顶级期刊(如Journal of Political Economy, American Economic Review)中使用PSM的实证研究
  • 关注因果推断领域最新工作论文(NBER, arXiv)

4.4 质量控制清单

在完成倾向值匹配分析后,使用以下清单检查质量:

  • [ ] 协变量选择是否基于因果图或领域知识?
  • [ ] 倾向值模型是否包含所有相关混杂因素?
  • [ ] 倾向值分布是否有足够重叠?
  • [ ] 匹配后所有协变量的标准化差异是否<0.1?
  • [ ] 匹配后样本量是否足够大?
  • [ ] 是否进行了敏感性分析?
  • [ ] 结论是否考虑了不可观测混杂因素的可能影响?

结论:从理论到实践的桥梁

倾向值匹配是连接观察性研究与因果推断的桥梁,它通过巧妙的统计设计模拟随机试验,为解决样本选择偏差提供了强大工具。掌握倾向值匹配需要理论理解与实践操作的结合:理解潜在结果框架和倾向值定理是基础,熟练实现匹配步骤和诊断是关键,识别并处理常见陷阱是进阶能力。

通过本文提供的完整学习路径,从理论基础到代码实现,再到高级主题和常见陷阱,你应该能够独立应用倾向值匹配解决实际问题。记住,倾向值匹配不是万能药,它依赖于”无未观测混杂”的强假设。因此,始终结合领域知识、进行敏感性分析,并谨慎解释结果,才能真正发挥其在因果推断中的价值。