Pandas DataFrame分层抽样:保留label列占比并解决异常多级索引问题
Pandas分层抽样去除二级索引的实现方案
原抽样逻辑已经实现了分层比例保留的核心需求,出现二级索引的原因是groupby方法的默认参数group_keys=True——该参数在启用时,会自动将分组键值作为外层索引拼接apply返回的各分组结果,最终形成带label层级的多级索引结构,并非抽样逻辑本身存在错误。
方案1:修改groupby参数适配无多余索引的输出
直接在groupby调用时指定group_keys=False,关闭自动添加分组键为索引的行为,最后统一重置为连续整数索引即可:
sampled_df = ( df.groupby('label', group_keys=False) # 关闭分组键自动加为外层索引的逻辑 .apply(lambda x: x.sample(frac=0.3, random_state=1)) .reset_index(drop=True) # 重排为从0开始的连续整数索引 )
- 抽样逻辑和原有写法完全一致,每个label分组按30%的比例无偏抽样,严格保持两类的原始占比
- 输出的DataFrame为单级连续整数索引,和常规DataFrame结构完全一致
方案2:使用专用分层抽样工具实现
不需要手动拼接分组逻辑,直接调用scikit-learn的分层拆分接口完成抽样,代码更简洁:
from sklearn.model_selection import train_test_split # 拆分时指定按label分层抽取30%的样本,丢弃剩下70%的样本 _, sampled_df = train_test_split( df, test_size=0.3, stratify=df['label'], # 指定按label列做分层,保持原始类别占比 random_state=1 ) sampled_df = sampled_df.reset_index(drop=True)
- 内部实现同样是按每个类别独立抽样,最终输出的类别占比和原数据集完全一致
- 接口经过多版本迭代兼容,不会出现多余人索引层级
结果校验
抽样完成后可通过两行代码确认是否符合要求:
# 校验类别占比,应输出1占0.6、0占0.4 print(sampled_df['label'].value_counts(normalize=True).round(2)) # 校验索引格式,应为常规连续整数RangeIndex print(sampled_df.index)
内容的提问来源于stack exchange,提问作者teller.py3
相关产品推荐
相关产品推荐

