Python 每组1:1分层抽样

Python 每组1:1分层抽样,python,pandas,multisampling,subsampling,Python,Pandas,Multisampling,Subsampling,如何在python中执行1:1分层抽样 假设熊猫数据帧df严重不平衡。它包含一个二进制组和多列分类子组 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

如何在python中执行1:1分层抽样

假设熊猫数据帧
df
严重不平衡。它包含一个二进制组和多列分类子组

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()
对于主
组==1
的每个成员,我需要找到
组==0
的单个匹配项


scikit learn中的
StratifiedShuffleSplit
仅返回随机数据部分,而不是1:1匹配。

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

输出

   group  id  sub_category_1  sub_category_2  value
4      0   5               1               1      2
2      0   3               2               2      3
请注意,此解决方案假定
组1
的每个可能子类别组合的大小小于
组0
中相应子组的大小。更健壮的版本包括使用替换:

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

有选择的版本与有排列的版本没有相同的假设,尽管它要求每个子类别组合至少有一个元素。

您的假设为1<0是可以的。但是,您仅计算组0的随机子样本。相反,我还需要考虑所有的子类别。我最初连接了所有列,即
group\u sub\u category\u 1\u sub\u category\u 2
,以生成新的类,但正如前面提到的那样,我被
stratifiedshuffliesplit
卡住了。对于
sub_category_1
sub_category_2
(事实上,对于真实数据集,它大约有10列)。情况也应该如此。但如果可能的话,如果它有足够的弹性来处理相同或更小的情况,那就太好了。但第一个案例已经很好了。@GeorgHeiler更新了答案!在您的输入示例中,组1和组0之间的子类别2之间没有公共值。只有一行。你不能得到与组1相同的分布,因为在子类2上没有值为2的元素。只需再添加一行就可以了。添加一行。
selected = np.ravel([np.random.choice(group.index, distribution[name], replace=True) for name, group in df.loc[mask].groupby(['label'])])