Python实现控制变量匹配抽样(对照匹配 case-control matching)

业务场景:广告业务中,需要分析优质素材和低质素材的差异,优质素材的定义就是高消耗的素材,在总体中占比仅10%,余下的均是低质素材。假设优质素材100条,低质素材900条,希望随机抽取100条和优质素材在控制变量上匹配的低质素材,进行后续的分析。
也就是说,,需要 控制变量匹配随机抽样——在保证对照组和实验组,在控制变量上属性相同的基础上,进行随机抽样。

实现的方法:

1、SPSS中有Case-control matching(个案控制匹配)的方法可以实现该抽样,具体可参考如下文章:

SPSS:病例-对照匹配(case-control matching)的实现过程 | Public Library of Bioinformatics

SPSS操作:搞定病例与对照的1:1匹配 - 知乎

2、用Python实现对照匹配抽样的方法,参考了这篇文章中SAS程序的思路,用Python实现。

病例对照、匹配(配对)抽样 SAS 程序(原创) - SAS专版 - 经管之家(原人大经济论坛)

测试数据如下:

数据表包含个案编号ID,需要匹配的变量 shcool、grade、class和age,分组变量group(1是实验组,0是对照组)。

ID

school

grade

class

name

age

group

1

AA

1

1

马莺琼

19

1

2

AA

1

1

范瑞娜

17

0

3

AA

1

1

陆艺

19

0

4

AA

1

1

韩薇婕

18

0

5

AA

1

2

黎舒

16

1

6

AA

1

2

江月菁

19

0

7

AA

1

2

詹枝静

18

0

8

AA

1

2

朱炎力

18

0

9

AA

2

1

游盛

16

1

10

AA

2

1

翁钧行

18

0

11

AA

2

1

潘策子

19

0

12

AA

2

1

姜富

19

0

13

AA

2

2

丁祥明

16

1

14

AA

2

2

柯龙

16

0

15

AA

2

2

钟永国

17

0

16

AA

2

2

卢巧

19

0

17

BB

1

1

孙俊龙

16

1

18

BB

1

1

童安伟

16

0

19

BB

1

1

沈强

16

0

20

BB

1

1

马致

20

0

21

BB

1

2

沈家康

16

1

22

BB

1

2

江弘

20

0

23

BB

1

2

阮建

18

0

24

BB

1

2

邵强

19

0

25

BB

2

1

黃巧

19

1

26

BB

2

1

罗影琦

20

0

27

BB

2

1

卓姬

16

0

28

BB

2

1

温姬娜

17

0

29

BB

2

2

庄倩

16

1

30

BB

2

2

曾悦

16

0

31

BB

2

2

汪娥莲

18

0

32

BB

2

2

欧丽茗

18

0

需求:

1)需要对数据做抽样,要求对实验组中的每一个案例,从对照组中随机抽样出school、grade、class相同,age相差不超过2岁的案例。

2)进行不放回抽样,也就是说,每一个已经被抽样出来的对照组案例,在后续的抽样中都不会再被抽到。

思路:

(1)拆分实验组和对照组的数据

(2)对实验组中的每个个案,根据school、grade、class、age匹配,找到符合条件的所有对照组个案,实现匹配

(3)从符合条件的所有对照组个案中,随机抽取一个,实现随机抽样

(4)将已抽取出来的对照组个案从对照组数据中删掉,实现不放回抽样

(5)循环处理所有的实验组个案


代码:

import pandas as pd
from random import choice

# 读取数据
file_path = './抽样测试数据.xlsx'
data = pd.read_excel(file_path)

# 显示前几行数据
data.head()

# 将数据拆分为实验组 (group=1) 和对照组 (group=0)
experimental_group = data[data['group'] == 1]
control_group = data[data['group'] == 0]

# 定义函数,对某一个特定的实验组个案,根据school、grade、class进行匹配,并确保age相差不超过2岁,筛选符合条件的控制组个案(0到多个)
def find_matching_cases(exp_case, control_group):  
    matching_cases = control_group[
        (control_group['school'] == exp_case['school']) &
        (control_group['grade'] == exp_case['grade']) &
        (control_group['class'] == exp_case['class']) &
        (control_group['age'].between(exp_case['age'] - 2, exp_case['age'] + 2))
    ]
    return matching_cases

# 列表存储已经抽取出来的控制组个案的ID,确保它不会再次被抽取
selected_control_indices = []

# 对实验组中的每一个个案,找到一个匹配的控制组个案
matched_samples = []
for _, exp_case in experimental_group.iterrows():
    # 调用前面的函数,筛选符合条件的控制组个案
    matching_control_cases = find_matching_cases(exp_case, control_group)
    # 从符合条件的控制组个案中,移除已经抽取过的个案
    matching_control_cases = matching_control_cases[~matching_control_cases.index.isin(selected_control_indices)]
    if not matching_control_cases.empty:
        # 在符合条件的控制组个案中,随机选一个出来
        selected_control_case = choice(matching_control_cases.to_dict('records'))
        matched_samples.append(selected_control_case)
        # 将抽取出的个案的ID加入列表
        selected_control_indices.append(selected_control_case['ID'])


# 把匹配样本输出到 DataFrame 中
matched_samples_df = pd.DataFrame(matched_samples)

# 显示前几行数据
matched_samples_df.head()  

实际业务应用场景中,将数据源和字段名替换即可。

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值