如何在Pandas中按多约束条件随机抽取3行样本?
解决方案:满足多条件的DataFrame随机抽样
我来帮你搞定这个兼顾多个约束的抽样需求!你已经拆分了价格区间,接下来要解决复合权重设置和供应商唯一性校验这两个核心问题,我们一步步来实现:
1. 先明确复合权重的构造逻辑
要同时优先选择margin更高、seen更低的行,不能直接用weights='margin'单字段权重。我们可以构造一个复合权重,让margin越高、seen越低的行拥有更大的抽样概率。比如用margin / (seen + 1)(加1是为了避免seen=0时出现除以0的错误),这个公式能很好地兼顾两个优先级:margin越大、seen越小,权重值就越大。
2. 分区间抽样+供应商唯一性校验
因为三个价格区间是互斥的,我们可以在每个区间单独按权重抽1行,然后检查这三行的供应商ID是否完全不同——如果有重复就重新抽取,直到满足条件为止。
完整实现代码
import pandas as pd import numpy as np # 假设你的原始数据集是pr_pd # 1. 拆分三个指定价格区间(修正边界逻辑,避免遗漏临界值) pr_1_pd = pr_pd.loc[pr_pd['price'] < 20.0].copy() pr_2_pd = pr_pd.loc[(pr_pd['price'] >= 30) & (pr_pd['price'] <= 50)].copy() pr_3_pd = pr_pd.loc[pr_pd['price'] > 80.0].copy() # 2. 为每个区间计算复合抽样权重 for df in [pr_1_pd, pr_2_pd, pr_3_pd]: # 权重公式:margin越高、seen越低,权重越大 df['sample_weight'] = df['margin'] / (df['seen'] + 1) # 3. 循环抽样,直到抽到三个供应商ID完全不同的样本 selected_rows = None while selected_rows is None or len(selected_rows['supplier'].unique()) != 3: # 每个区间按自定义权重抽取1行 sample_low = pr_1_pd.sample(n=1, weights='sample_weight', random_state=np.random.randint(0, 10000)) sample_mid = pr_2_pd.sample(n=1, weights='sample_weight', random_state=np.random.randint(0, 10000)) sample_high = pr_3_pd.sample(n=1, weights='sample_weight', random_state=np.random.randint(0, 10000)) # 合并三个区间的样本 selected_rows = pd.concat([sample_low, sample_mid, sample_high]).reset_index(drop=True) # 清理临时权重列,输出结果 selected_rows = selected_rows.drop(columns=['sample_weight']) print("最终符合条件的抽样结果:") print(selected_rows)
关键细节说明
- 权重调整:如果你觉得
margin/(seen+1)的权重偏向不够,可以换成其他公式,比如margin * (pr_pd['seen'].max() - df['seen'] + 1)——先把seen转换为“反向数值”(seen越小数值越大),再和margin相乘,同样能实现你的优先级需求。 - 循环逻辑:因为不同价格区间可能存在相同的供应商ID,循环抽样是最直接的校验方式。如果你的数据中跨区间重复的供应商很少,这个循环只会执行1-2次,效率很高。
- 区间边界:把中间区间的条件改成
>=30和<=50,避免漏掉刚好等于30或50的行,更贴合你“30到50之间”的需求。
内容的提问来源于stack exchange,提问作者IndiaSke
相关产品推荐
相关产品推荐

