如何在Pandas DataFrame中添加随机选中状态列?
解决Pandas分组后随机选行并标记的问题
我完全理解你的需求:按A列分组后每组无放回随机选10行,最后给原始未分组的DataFrame新增一列标记哪些行被选中。这其实用Pandas内置方法就能轻松实现,甚至不需要额外依赖NumPy,下面一步步给你拆解:
步骤1:准备示例数据(方便演示)
先模拟一个和你场景匹配的DataFrame,方便后续操作验证:
import pandas as pd import numpy as np # 生成示例数据:A列包含3个分组,每个分组100行数据 df = pd.DataFrame({ 'A': np.repeat(['Group1', 'Group2', 'Group3'], 100), 'OtherData': np.random.randn(300) })
步骤2:分组抽样并获取选中行的索引
Pandas的groupby().sample()方法默认就是无放回抽样,我们直接用它抽取每组的10行,然后提取这些行的索引:
# 按A列分组,每组随机选10行,拿到选中行的索引集合 sampled_rows_index = df.groupby('A').sample(n=10).index
步骤3:给原始DataFrame添加标记列B
用isin()方法判断每行的索引是否在抽样得到的索引集合里,直接生成True/False的标记列:
# 新增B列,标记该行是否被选中 df['B'] = df.index.isin(sampled_rows_index)
验证结果是否符合要求
可以快速检查每个分组中被标记为True的行数是否为10:
# 查看每个分组里选中行的数量 print(df.groupby('A')['B'].sum())
输出结果应该每个分组对应数值都是10,完美符合需求。
可选:用NumPy实现抽样逻辑
如果你更习惯用NumPy来处理抽样,也可以用下面的方式实现:
def mark_sampled_rows(group): # 在组内随机生成10个不重复的行位置 sample_pos = np.random.choice(len(group), size=10, replace=False) # 初始化标记列,然后给选中位置设为True group['B'] = False group.iloc[sample_pos, group.columns.get_loc('B')] = True return group # 分组应用自定义函数 df = df.groupby('A').apply(mark_sampled_rows)
这个方法和前面的结果完全一致,只是用NumPy的random.choice实现了抽样逻辑。
两种方法都能满足你的需求,其中Pandas原生的sample()方法更简洁高效,推荐优先使用。
内容的提问来源于stack exchange,提问作者Stephen Frost
相关产品推荐
相关产品推荐

