如何在Pandas数据采样中确保涵盖全部品牌与类别且每个品牌取10行
解决方案:满足多条件的Pandas采样需求
我完全明白你的痛点——普通的sample()随机采样没法保证品牌和类别的全覆盖,groupby又只能拿到唯一值,没法满足每个品牌至少10行的要求。结合你的数据集规模(100万行)和需求,我给你设计了一套分步采样的方案,完美满足所有条件:
核心思路
先确保每个品牌至少10行的硬要求,再补全未覆盖的类别,最后用随机采样填充到10000行总样本数,同时避免重复采样。
具体代码实现
import pandas as pd # 假设你的原始数据集是df # 第一步:给每个品牌随机抽取10行,确保品牌全覆盖+每个品牌至少10行 brand_samples = df.groupby('brand_name').apply( lambda group: group.sample(n=10, random_state=42) # random_state保证结果可复现 ).reset_index(drop=True) # 记录已采样的行索引,避免后续重复抽取 sampled_indices = set(brand_samples.index) remaining_df = df[~df.index.isin(sampled_indices)] # 第二步:补全未被覆盖的类别,确保所有类别都出现在样本中 covered_cats = set(brand_samples['category'].unique()) all_cats = set(df['category'].unique()) missing_cats = all_cats - covered_cats category_supplement = pd.DataFrame() for cat in missing_cats: # 从剩余数据中取该类别的任意一行 cat_rows = remaining_df[remaining_df['category'] == cat] if not cat_rows.empty: category_supplement = pd.concat([category_supplement, cat_rows.sample(n=1, random_state=42)]) # 更新已采样索引和剩余数据 sampled_indices.update(category_supplement.index) remaining_df = df[~df.index.isin(sampled_indices)] # 第三步:计算还需要的样本量,从剩余数据中随机抽取补充 needed_samples = 10000 - len(brand_samples) - len(category_supplement) final_supplement = remaining_df.sample(n=needed_samples, random_state=42) # 合并所有样本得到最终结果 final_sample = pd.concat([brand_samples, category_supplement, final_supplement]).reset_index(drop=True)
验证结果是否符合要求
可以运行以下代码确认所有条件都满足:
# 验证所有品牌都被包含 assert len(final_sample['brand_name'].unique()) == len(df['brand_name'].unique()), "存在未覆盖的品牌" # 验证所有类别都被包含 assert len(final_sample['category'].unique()) == len(df['category'].unique()), "存在未覆盖的类别" # 验证每个品牌至少有10行 assert all(final_sample.groupby('brand_name').size() >= 10), "有品牌的样本量不足10行" # 验证总样本数为10000 assert len(final_sample) == 10000, "总样本数不符合要求"
方案优势
- 优先级明确:先满足品牌的最低行数要求,再补全类别,最后保持随机采样的代表性
- 高效处理百万级数据:所有操作都是Pandas原生函数,性能拉满
- 结果可复现:通过
random_state固定随机种子,方便后续调试和重复实验
内容的提问来源于stack exchange,提问作者Niyamat Ullah
相关产品推荐
相关产品推荐

