如何用pandas各取真实、虚假账号数据集50%样本合并为新数据集?
真假账号各占50%平衡数据集实现方法
你当前场景不需要用.join(),这个方法是用来横向拼接不同字段的,你需要的是先分别对两类账号做随机抽样,再纵向拼接样本行即可,具体步骤如下:
- 先给两个数据集新增类别标签列,避免拼接后无法区分样本所属类别
- 确定单类样本的抽样数量:如果要抽取每个数据集自身半数样本,直接取对应数据集总行数的50%即可;如果要保证最终数据集两类样本严格1:1(更常用的平衡采样逻辑),取两个数据集样本量的最小值作为单类抽样数即可,避免某类样本总量不足
- 用pandas内置的
.sample()方法做无放回随机抽样,固定random_state参数可以保证结果可复现 - 用
pd.concat()纵向拼接两个抽样后的子集,最后打乱整体行顺序就得到最终数据集
场景1:抽取每个数据集自身半数样本合并
该方式要求两个原始数据集的总行数一致,才能保证合并后真假账号刚好各占50%,完整代码如下:
import pandas as pd # 已完成的数据集导入 dataset_genuine = pd.read_csv('users_genuine.csv') dataset_fake = pd.read_csv('users_fake.csv') # 新增类别标签列 dataset_genuine['label'] = 'genuine' dataset_fake['label'] = 'fake' # 计算单类半数抽样量,向下取整避免样本数溢出 sample_num_genuine = int(len(dataset_genuine) * 0.5) sample_num_fake = int(len(dataset_fake) * 0.5) # 无放回随机抽样 genuine_subset = dataset_genuine.sample(n=sample_num_genuine, random_state=42, replace=False) fake_subset = dataset_fake.sample(n=sample_num_fake, random_state=42, replace=False) # 纵向拼接并重置索引 balanced_df = pd.concat([genuine_subset, fake_subset], ignore_index=True) # 打乱整体行顺序,避免真假样本分段聚集 balanced_df = balanced_df.sample(frac=1, random_state=42).reset_index(drop=True)
场景2:通用1:1平衡采样(推荐)
如果两个原始数据集的总行数差异较大,抽各自半数会导致最终占比偏离1:1,此时取两类样本的最小总量作为统一抽样量即可,仅需要修改抽样量计算部分的代码:
# 取两类样本的最小总量作为单类抽样数,保证两类样本量完全相等 sample_num = min(len(dataset_genuine), len(dataset_fake)) # 如果仍想保留“抽半数”的逻辑,可以把抽样量设为最小总量的一半 # sample_num = int(min(len(dataset_genuine), len(dataset_fake)) * 0.5) genuine_subset = dataset_genuine.sample(n=sample_num, random_state=42, replace=False) fake_subset = dataset_fake.sample(n=sample_num, random_state=42, replace=False) balanced_df = pd.concat([genuine_subset, fake_subset], ignore_index=True) balanced_df = balanced_df.sample(frac=1, random_state=42).reset_index(drop=True)
补充说明:如果需要验证最终数据集的类别占比,可以执行
print(balanced_df['label'].value_counts(normalize=True)),输出结果会显示两类样本的占比,确认是否符合各50%的要求。
内容的提问来源于stack exchange,提问作者Xie
相关产品推荐
相关产品推荐

