降采样超过 2 类

Downsampling for more than 2 classes

我正在创建一个简单的代码,它允许在目标变量超过 2 个时对数据帧进行下采样 类。

df 为我们的任意数据集,'TARGET_VAR' 为超过 2 类.

的分类变量
import pandas as pd
label='TARGET_VAR' #define the target variable

num_class=df[label].value_counts() #creates list with the count of each class value
temp=pd.DataFrame() #create empty dataframe to be filled up

for cl in num_class.index: #loop through classes
    #iteratively downsample every class according to the smallest
    #class 'min(num_class)' and append it to the dataframe.
    temp=temp.append(df[df[label]==cl].sample(min(num_class)))

df=temp #redefine initial dataframe as the subsample one

del temp, num_class #delete temporary dataframe

现在我想知道,有没有办法更精致地做到这一点?例如无需创建临时数据集? 我试图找出一种方法来 "vectorize" 对多个 类 进行操作,但没有取得任何进展。下面是我的想法,可以很容易地为 2 类 实现,但我不知道如何将它扩展到多个 类 的情况。

如果您有 2 个 类

,这将非常有效
 df= pd.concat([df[df[label]==num_class.idxmin()],\
 df[df[label]!=num_class.idxmin()].sample(min(num_class))])

这使您可以为另一个 类 选择合适数量的观察值,但 类 不一定得到平等的代表。

 df1= pd.concat([df[df[label]==num_class.idxmin()],\
 df[df[label]!=num_class.idxmin()].sample(min(num_class)*(len(num_class)-1))])

您可以尝试类似的操作:

label='TARGET_VAR'

g = df.groupby(label, group_keys=False)
balanced_df = pd.DataFrame(g.apply(lambda x: x.sample(g.size().min()))).reset_index(drop=True)

我相信这会产生你想要的结果,欢迎随时提问。

编辑

根据 OP 的建议修复了代码。

此代码用于 oversampling 个少数 class 实例或 undersampling 个多数 class 实例。它应该只在训练集上使用。注:activity是标签

balanced_df=Pdf_train.groupby('activity',as_index = False,group_keys=False).apply(lambda s: s.sample(100,replace=True))

Gustavo 的答案是正确的,但有一个小问题(由于某些原因我无法编辑他的答案)。

label='TARGET_VAR'

g = df.groupby(label, group_keys=False)
balanced_df = pd.DataFrame(g.apply(lambda x: 
x.sample(g.size().min()).
reset_index(drop=True)))

此处将为每个组重置索引,最终数据帧将具有重复的行索引。如果我们定义少数class中的元素个数为n:

idx, data 
0,   ...
1,   ...
.,   ...
.,   ...
.,   ...
n,   ...
0,   ...
1,   ...
.,   ...
.,   ...
.,   ...
n,   ...

以下调整将解决问题

g = df.groupby(label, group_keys=False)
balanced_df = pd.DataFrame(g.apply(lambda x: 
x.sample(g.size().min()))).reset_index(drop=True)

如果我们现在定义balanced_df的元素总数为N=n*kk是不同class的个数。索引将如下所示:

idx, data 
0,   ...
1,   ...
.,   ...
.,   ...
.,   ...
N,   ...