如何在Pandas中按组等概率随机采样行(非固定每组行数)

本文介绍一种巧妙策略:先对每个分组均匀过采样,再全局随机抽取目标行数,从而实现各组被选中的概率近似相等,避免因组大小差异导致的偏差。

本文介绍一种巧妙策略:先对每个分组均匀过采样,再全局随机抽取目标行数,从而实现各组被选中的概率近似相等,避免因组大小差异导致的偏差。

在使用 pandas.DataFrame.groupby().sample() 时,若指定 n=k,则会强制从每个组中精确抽取 k 行——这适用于“每组取固定数量”的场景;但当目标是“让每个组被抽中的概率大致相同”(即组间无偏采样),而非保证每组样本数一致时,需采用更灵活的方法。

核心思路是两阶段采样:

  1. 第一阶段(组内均衡化):计算目标总样本量 N 与唯一组数 n_groups 的比值,向上取整得到每组应初步采样的行数 ceil(N / n_groups),并对每组独立、有放回地采样该数量;
  2. 第二阶段(全局随机化):从第一阶段结果中无放回地随机抽取 N 行,消除组内过采样引入的冗余,最终使各组出现频率趋近于 1 / n_groups。

以下是完整实现代码:

import pandas as pd
import math

# 示例数据
df = pd.DataFrame({
    'ID': ['a', 'a', 'b', 'c', 'c', 'c'],
    'Value': [2, 4, 6, 8, 10, 12]
})

N = 4  # 目标总采样行数
n_groups = df['ID'].nunique()

out = (df.groupby('ID')
       .sample(n=math.ceil(N / n_groups), replace=True)
       .sample(N)  # 无放回全局重采样
       .reset_index(drop=True))

print(out)

优势说明

可赞AI

文字一秒可视化,免费AI办公神器

  • 不依赖各组原始大小,即使某组仅1行(如 'b' 组),也能参与等概率竞争;
  • 随着 N 增大,各组实际占比快速收敛至理论均值(如 3 组 → 每组 ≈ 33.3%);
  • replace=True 在第一阶段确保小规模组不被忽略,sample(N) 在第二阶段保障输出严格为 N 行。

⚠️ 注意事项

  • 若 N < n_groups(如 N=2 但有3个组),math.ceil(2/3)=1,第一阶段每组采1行共3行,第二阶段再从中选2行——仍能保证组间公平;
  • 该方法默认各组权重相同;如需自定义组权重(如按组大小加权),应改用 df.sample(frac=1, weights=...) 配合预计算权重列;
  • 结果不保证每组至少出现一次(小概率事件),若需强制覆盖所有组,建议结合 groupby().apply(lambda g: g.sample(1)) 后补足剩余名额。

综上,该两阶段采样法以简洁代码实现了统计意义上的组间无偏抽样,是处理不均衡分组数据时的实用技巧。

相关推荐:

LightGBM在Python下为什么比XGBoost快_基于直方图算法与单边梯度采样

LightGBM比XGBoost快的核心原因是直方图特征离散化和GOSS采样:前者将连续特征映射为整数桶,降低排序与增益计算复杂度;后者保留高梯度样本并加权采样低梯度样本,减少数据遍历量。 LightGBM在Python下比XGBoost快,核心原因不是“代码写得更精简”,而是算法层面的两个关键设计...

如何在不支持重触发的NI USB-6002设备上实现高密度外部触发AI采样

本文介绍一种绕过niusb-6002硬件限制的实用方案:通过双通道同步模拟采集(ai0+ai1)记录触发信号与目标信号,再结合离线边缘检测精准截取每触发对应的2–5个采样点,成功支持最小1ms间隔的非均匀外部触发采集。 本文介绍一种绕过niusb-6002硬件限制的实用方案:通过双通道同步模拟采集(...

Python类中正确实现列表随机打乱的实践指南

在Python类初始化时直接对传入列表调用random.shuffle()会导致多个实例共享同一份被修改的数据,根本原因是未创建独立副本;解决方法是使用.copy()或list()构造新列表后再打乱。 在python类初始化时直接对传入列表调用`random.shuffle()`会导致多个实例共享同...

Python中如何处理数据倾斜严重的分类任务_使用SMOTE算法过采样

SMOTE不是万能开关,用错位置、时机或参数会降低模型性能;根本原因是未标准化导致量纲主导邻域搜索、数据泄露造成验证失真、k值不当生成噪声样本,以及误用sklearn而非imblearn库。 SMOTE不是“一加就灵”的开关,用错位置、用错时机、用错参数,反而会让模型在测试集上F1下降、precis...