pandas DataFrame如何按列唯一值随机抽取指定比例的行并打标?
最优实现方案
直接使用pandas内置的GroupBy.sample方法即可实现无遍历的向量化操作,代码极其简洁:
import pandas as pd # 读入源数据 df = pd.read_csv('source.csv') # 按Person分组,每组抽取10%的样本,获取选中行的索引 # 可添加random_state参数固定抽样结果,方便复现 selected_index = df.groupby('Person', group_keys=False).sample(frac=0.1, random_state=42).index # 新增选中标记列 df['selected'] = '' df.loc[selected_index, 'selected'] = 'bingo!'
方案优势
- 完全依赖pandas底层优化的向量化接口,没有显式遍历逻辑,性能远高于自定义循环/逐行apply的实现
- 代码逻辑清晰,仅需3行核心代码即可完成需求,符合Pythonic的简洁风格
- 无需额外的merge操作、辅助表、自定义判断函数,避免了不必要的内存开销和逻辑冗余
可选兼容方案(适配低版本pandas/需要保底抽样)
如果你的pandas版本低于1.1.0不支持GroupBy.sample,或者需要保证每组至少抽1条样本(避免组行数小于10时抽到0条的情况),可以用随机排名的方式实现:
import pandas as pd import numpy as np df = pd.read_csv('source.csv') # 组内生成随机排名 df['group_rand_rank'] = df.groupby('Person')['Person'].transform(lambda x: np.random.permutation(len(x))) # 计算每组需要抽取的样本数,max(1)保证每组至少1条 df['group_sample_cnt'] = df.groupby('Person')['Person'].transform(lambda x: max(1, int(len(x)*0.1))) # 标记选中行 df['selected'] = np.where(df['group_rand_rank'] < df['group_sample_cnt'], 'bingo!', '') # 清理辅助列 df.drop(columns=['group_rand_rank', 'group_sample_cnt'], inplace=True)
内容的提问来源于stack exchange,提问作者P E
相关产品推荐
相关产品推荐

