每组python 1:1分层抽样 [英] python 1:1 stratified sampling per each group

查看:416
本文介绍了每组python 1:1分层抽样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在python中进行1:1分层采样?

How can a 1:1 stratified sampling be performed in python?

假定熊猫数据框df严重失衡.它包含一个二进制组和多列类别子组.

Assume the Pandas Dataframe df to be heavily imbalanced. It contains a binary group and multiple columns of categorical sub groups.

df = pd.DataFrame({'id':[1,2,3,4,5], 'group':[0,1,0,1,0], 'sub_category_1':[1,2,2,1,1], 'sub_category_2':[1,2,2,1,1], 'value':[1,2,3,1,2]})
display(df)
display(df[df.group == 1])
display(df[df.group == 0])
df.group.value_counts()

对于主group==1的每个成员,我需要找到group==0与的单个匹配项.

For each member of the main group==1 I need to find a single match of group==0 with.

scikit-learn中的StratifiedShuffleSplit只会返回数据的随机部分,而不是1:1匹配.

A StratifiedShuffleSplit from scikit-learn will only return a random portion of data, not a 1:1 match.

推荐答案

如果我正确理解,则可以使用

If I understood correctly you could use np.random.permutation:

import numpy as np
import pandas as pd

np.random.seed(42)

df = pd.DataFrame({'id': [1, 2, 3, 4, 5], 'group': [0, 1, 0, 1, 0], 'sub_category_1': [1, 2, 2, 1, 1],
                   'sub_category_2': [1, 2, 2, 1, 1], 'value': [1, 2, 3, 1, 2]})

# create new column with an identifier for a combination of categories
columns = ['sub_category_1', 'sub_category_2']
labels = df.loc[:, columns].apply(lambda x: ''.join(map(str, x.values)), axis=1)
values, keys = pd.factorize(labels)
df['label'] = labels.map(dict(zip(keys, values)))

# build distribution of sub-categories combinations
distribution = df[df.group == 1].label.value_counts().to_dict()

# select from group 0 only those rows that are in the same sub-categories combinations
mask = (df.group == 0) & (df.label.isin(distribution))

# do random sampling
selected = np.ravel([np.random.permutation(group.index)[:distribution[name]] for name, group in df.loc[mask].groupby(['label'])])

# display result
result = df.drop('label', axis=1).iloc[selected]
print(result)

输出

   group  id  sub_category_1  sub_category_2  value
4      0   5               1               1      2
2      0   3               2               2      3

请注意,此解决方案假定group 1的每个可能的sub_category组合的大小小于group 0中的相应子组的大小.一个更强大的版本涉及使用 np.random.choice 替换:

Note that this solution assumes the size of the each possible sub_category combination of group 1 is less than the size of the corresponding sub-group in group 0. A more robust version involves using np.random.choice with replacement:

selected = np.ravel([np.random.choice(group.index, distribution[name], replace=True) for name, group in df.loc[mask].groupby(['label'])])

带有选择版本的版本与带有置换版本的假设不同,尽管每个子类别组合至少需要一个元素.

The version with choice does not have the same assumption as the one with permutation, although it requires at least one element for each sub-category combination.

这篇关于每组python 1:1分层抽样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆