因果推断(二)倾向匹配得分(PSM)

article/2025/6/30 10:42:57

因果推断(二)倾向匹配得分(PSM)

前文介绍了如何通过合成控制法构造相似的对照组,除此之外,也可以根据倾向匹配得分(PSM)进行构造,即为每一个试验组样本在对照组中找对与之相似的样本进行匹配。PSM 通过统计学模型计算每个样本的每个协变量的综合倾向性得分,再按照倾向性得分是否接近进⾏匹配。本文参考自PSM倾向得分匹配法。

⚠️注意:倾向匹配得分常用于截面数据

数据准备

# !pip install psmatching
import psmatching.match as psm
import pytest
import pandas as pd
import numpy as np
from psmatching.utilities import *
import statsmodels.api as sm

以下数据如果有需要的同学可关注公众号HsuHeinrich,回复【因果推断02】自动获取~

# 读取数据
path = "psm_data.csv"
raw_data = pd.read_csv(path)
raw_data.set_index("ID", inplace=True)
raw_data.head()

image-20230206154724976

倾向得分与匹配

  • 自定义函数
# 计算propensity
def cal_propensity(df, formula, k):df=df.copy()# 利用逻辑回归框架计算倾向得分,即广义线性估计 + 二项式Binomialglm_binom = sm.formula.glm(formula = formula, data = df, family = sm.families.Binomial())# 模型拟合result = glm_binom.fit()# 计算propensity scorepropensity_scores = result.fittedvaluesdf["PROPENSITY"] = propensity_scoresreturn df# 计算matched_data
def cal_matched_data(df, treatment, propensity, k):groups = df[treatment] # 干预项propensity = df[propensity]# 把干预项替换成True和Falsegroups = groups == groups.unique()[1]n = len(groups)# 计算True和False的数量n1 = groups[groups==1].sum()n2 = n-n1g1, g2 = propensity[groups==1], propensity[groups==0]# 确保n2>n1,,少的匹配多的,否则交换下if n1 > n2:n1, n2, g1, g2 = n2, n1, g2, g1# 随机排序干预组,减少原始排序的影响np.random.seed(0)m_order = list(np.random.permutation(groups[groups==1].index))# 根据倾向评分差异将干预组与对照组进行匹配# 注意:caliper = None可以替换成自己想要的精度matches = {}k = int(k)print("\n给每个干预组匹配 [" + str(k) + "] 个对照组 ... ", end = " ")for m in m_order:# 计算所有倾向得分差异,这里用了最粗暴的绝对值# 将propensity[groups==1]分别拿出来,每一个都与所有的propensity[groups==0]相减dist = abs(g1[m]-g2)array = np.array(dist)# 如果无放回地匹配,最后会出现要选取3个匹配对象,但是只有一个候选对照组的错误,故进行判断if k < len(array):# 在array里面选择K个最小的数字,并转换成列表k_smallest = np.partition(array, k)[:k].tolist()# 用卡尺做判断caliper = Noneif caliper:caliper = float(caliper)# 判断k_smallest是否在定义的卡尺范围keep_diffs = [i for i in k_smallest if i <= caliper]keep_ids = np.array(dist[dist.isin(keep_diffs)].index)else:# 如果不用标尺判断,那就直接上k_smallest了keep_ids = np.array(dist[dist.isin(k_smallest)].index)#  如果keep_ids比要匹配的数量多,那随机选择下,如要少,通过补NA配平数量if len(keep_ids) > k:matches[m] = list(np.random.choice(keep_ids, k, replace=False))elif len(keep_ids) < k:while len(matches[m]) <= k:matches[m].append("NA")else:matches[m] = keep_ids.tolist()# 判断 replace 是否放回replace = Falseif not replace:g2 = g2.drop(matches[m])# 将匹配完成的结果合并起来matches = pd.DataFrame.from_dict(matches, orient="index")matches = matches.reset_index()column_names = {}column_names["index"] = "干预组"for i in range(k):column_names[i] = str("匹配对照组_" + str(i+1))matches = matches.rename(columns = column_names)print("\n匹配完成!")return matches# 变量校验
def var_val(df, treatment):variables = df.columns.tolist()[0:-2]results = {}print("开始评估匹配 ...")#注意:将PUSH替换成自己的干预项for var in variables:# 制作用于卡方检验的频率计数交叉表crosstable = pd.crosstab(df[treatment],df[var])if len(df[var].unique().tolist()) <= 2:# 计算 2x2 表的卡方统计量、df 和 p 值p_val = calc_chi2_2x2(crosstable)[1]else:# 计算 2x2 表的卡方统计量、df 和 p 值p_val = calc_chi2_2xC(crosstable)[1]results[var] = p_valprint("\t" + var + '(' + str(p_val) + ')', end = "")if p_val < 0.05:print(": 未通过")else:print(": 通过")if True in [i < 0.05 for i in results.values()]:print("\n变量未全部通过匹配")else:print("\n变量全部通过匹配")
  • 计算得分
# 计算propensity
k=3
formu='PUSH ~ AGE + SEX + VIP_LEVEL + LASTDAY_BUY_DIFF \+ PREFER_TYPE + LOGTIME_PREFER + USE_COUPON_BEFORE + ACTIVE_LEVEL'
df_model=cal_propensity(raw_data, formu, k)
  • 匹配相似组
# 计算干预=1的匹配组
matches=cal_matched_data(df_model, 'PUSH', 'PROPENSITY', 3)
给每个干预组匹配 [3] 个对照组 ...  
匹配完成!
# 提取全部干预与倾向匹配数据
# 这里直接调用get_matched_data,注意输入的matches是匹配结果,raw_data是全部数据
matched_data = get_matched_data(matches, raw_data)
  • 变量校验
# 变量校验
var_val(df_model, 'PUSH')
开始评估匹配 ...AGE(0.9904): 通过SEX(0.6688): 通过VIP_LEVEL(0.0089): 未通过LASTDAY_BUY_DIFF(0.5134): 通过PREFER_TYPE(0.7107): 通过LOGTIME_PREFER(0.2442): 通过USE_COUPON_BEFORE(0.2961): 通过ACTIVE_LEVEL(0.7934): 通过变量未全部通过匹配

总结

如果产品告诉你,我们发现使用A功能的用户比没有使用A功能的用户留存率提高了30%。如果你持有怀疑态度,就可以尝试通过PSM为每一个实验样本与之相似的样本,构造出相似的对照组后发现差异并没有很多(例如只有10%),你就可以理直气壮的驳斥他们了。

共勉~


http://chatgpt.dhexx.cn/article/UjNaZ1I7.shtml

相关文章

PSM倾向得分匹配代码和案例数据

PSM倾向得分匹配代码和案例数据 含义&#xff1a;倾向评分匹配&#xff08;Propensity Score Matching&#xff0c;简称PSM&#xff09;是一种统计学方法&#xff0c;用于处理观察研究&#xff08;Observational Study&#xff09;的数据。 在观察研究中&#xff0c;由于种种…

倾向得分匹配PSM案例分析

倾向得分匹配(PSM)&#xff0c;是一种模仿RCT随机对照试验随机化分组&#xff0c;提高组间均衡性&#xff0c;进而达到降低混杂因素影响目的一种数据处理策略。PSM在计量研究&#xff0c;临床医学等领域有着广泛的应用。 1.案例背景与分析策略 1.1 案例背景介绍 某企业想评价…

使用R进行倾向得分匹配(PSM)

【译文】使用R进行倾向得分匹配&#xff08;PSM&#xff09; 作者 Norbert Khler 译者 钱亦欣 根据维基百科&#xff0c;倾向得分匹配&#xff08;PSM&#xff09;是一种用来评估处置效应的统计方法。广义说来&#xff0c;它将样本根据其特性分类&#xff0c;而不同类样本间…

倾向匹配得分PSM学习笔记

一直在想写倾向匹配得分PSM学习笔记&#xff0c;好好总结一下。但一直拖着&#xff0c;对倾向匹配得分法虽然思想比较理解&#xff0c;但没有系统地学习&#xff0c;所以这篇博客总结一下老师们的一些文章&#xff0c;在总结中学习&#xff0c;哈哈~ 倾向匹配得分PSM学习笔记 …

倾向得分匹配案例分析

一、倾向得分匹配法说明 倾向得分匹配模型是由Rosenbaum和Rubin在1983年提出的&#xff0c;首次运用在生物医药领域&#xff0c;后来被广泛运用在药物治疗、计量研究、政策实施评价等领域。倾向得分匹配模型主要用来解决非处理因素&#xff08;干扰因素&#xff09;的偏差。 …

倾向得分匹配法(PSM)量化评估效果分析

1. 因果推断介绍 如今量化策略实施的效果评估变得越来越重要&#xff0c;数据驱动产品和运营、业务等各方的理念越来越受到重视。如今这方面流行的方法除了实验方法AB testing外&#xff0c;就是因果推断中的各种观察研究方法。 “统计相关性并不意味着因果关系”&#xff0c;数…

PSM倾向得分匹配法【python实操篇】

前言 大家好&#xff0c;我是顾先生&#xff0c;PSM倾向性得分匹配法的Python代码实操终于来啦&#xff01; ​ 对于PSM原理不太熟悉的同学可以看看前一篇文章&#xff1a;PSM倾向得分匹配法【上篇&#xff1a;理论篇】 目前网上PSM实操的相关文章都是R语言、SPSS和STATA实现…

数据分析36计(九):倾向得分匹配法(PSM)量化评估效果分析

1. 因果推断介绍 如今量化策略实施的效果评估变得越来越重要&#xff0c;数据驱动产品和运营、业务等各方的理念越来越受到重视。如今这方面流行的方法除了实验方法AB testing外&#xff0c;就是因果推断中的各种观察研究方法。 “统计相关性并不意味着因果关系”&#xff0c;数…

PSM倾向得分匹配

1. 简要介绍 我们以 是否上大学 () 对 收入 () 的影响为例来说明这个问题。这里&#xff0c;先讲二者的关系设定为如下线性模型&#xff1a; 显然&#xff0c;在模型 (1) 的设定中&#xff0c;我们可能忽略了一些同时影响「解释变量」—— 是否上大学 () 和「被解释变量」——…

stata 倾向得分匹配操作

倾向得分匹配法是一种研究方法&#xff0c;它在研究某项治疗、政策、或者其他事件的影响因素上很常见。对于经济、金融学领域来说&#xff0c;比如需要研究某个劳动者接受某种高等教育对其收入的影响&#xff0c;或者比如研究某个企业运用了某项管理层激励措施以后对企业业绩的…

倾向得分匹配(PSM)的原理以及应用

该文章主要介绍倾向得分匹配&#xff08;PSM, Propensity Score Matching&#xff09;方法的原理以及实现。这是一种理论稍微复杂、但实现较为容易的分析方法&#xff0c;适合非算法同学的使用。可用于&#xff08;基于观察数据的&#xff09;AB实验、增量模型搭建等领域。 文章…

倾向得分匹配只看这篇就够了

一、倾向得分匹配法说明 倾向得分匹配模型是由Rosenbaum和Rubin在1983年提出的&#xff0c;首次运用在生物医药领域&#xff0c;后来被广泛运用在药物治疗、计量研究、政策实施评价等领域。倾向得分匹配模型主要用来解决非处理因素&#xff08;干扰因素&#xff09;的偏差。 …

Android设置图标背景透明

这里写自定义目录标题 Android 设置图标背景透明速览引言调整背景色 Android 设置图标背景透明 速览 设置 android:background"#00ffffff" 引言 适用于 Vector Assets 和 透明背景的图片 想要在Android中使用透明背景的图片 首先得保证图片本身是透明背景的 不然也没…

如何设置背景透明度

设置背景透明度分为两种&#xff1a;一种背景为颜色设置的纯色背景&#xff1b;另一种是图片做背景。 【情况一】纯色背景 关键代码&#xff1a;background:rgba(R,G,B,A) RGB--------三原色&#xff08;red,green,bule&#xff09;A-------透明度 关于三原色最终成型的颜色…

html悬浮背景透明视频教程,在html中使用背景透明的video视频

由于对效果的要求&#xff0c;需要加入透明背景的video。经过了解&#xff0c;现代浏览器(新版 Chrome、Firefox、Safari 等)已经全面支持 webM 格式的视频了&#xff0c;因此可以使用带 alpha 通道的 webM 格式视频满足要求。 要得到透明 webM 格式视频&#xff0c;则需要来源…

Android BottomSheetDialog设置背景透明无效?(解决)

BottomSheetDialog修改背景圆角 解决方法 这里记录一个实际开发过程中遇到的问题&#xff0c;在日常开发中遇到底部弹窗的时候我会第一时间用到BottomSheetDialog&#xff0c;常规的使用就是有一个默认从底部出现的弹窗&#xff0c;但是为了美观&#xff0c;通常会使用圆角&…

dialog设置背景透明

默认dialog是一个白底方形的&#xff0c;如果在xml设置中设置了一种边角是弧形的背景图片&#xff0c;那么显现的dialog角落就会留白 &#xff0c;解决办法&#xff1a; dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); 效果&#xff1a;只…

Flutter bottomNavigationBar背景透明

Scaffold(extendBody: true,//加这句背景就透明 ..... ) 效果图

html+页面的背景透明,css设置背景透明 元素不透明

css设置背景透明 元素不透明 在做前端页面的时候&#xff0c;我们会遇到这样的情况&#xff0c;需要背景为半透明状态&#xff0c;但是层里面的内容不需要为透明的状态。有时候我们设置的时候会出现不管内容还是背景同时都成透明了&#xff0c;如何实现背景色透明但内容不透明这…