如何在np.random.choice循环生成组合时避免指定元素同时出现
解决方案
提供两种可直接使用的实现方案,你可以根据实际场景选择:
方案1:过滤法(实现最简单,10000次抽样场景完全够用)
该方案会在生成样本后校验规则,仅保留符合要求的样本,完全保留你原始的加权无放回抽样的概率分布:
import numpy as np # 替换为你的实际城市列表、抽样概率 cities = ['RO', 'MI', 'VE', 'NA', 'SI'] cities_prob = [0.2, 0.2, 0.2, 0.2, 0.2] np.random.seed(42) portfolio = [] sample_count = 10000 while len(portfolio) < sample_count: port_gar = list(np.random.choice(cities, size=4, replace=False, p=cities_prob)) # 校验规则:RO和SI不同时存在则保留 if not ('RO' in port_gar and 'SI' in port_gar): portfolio.append(port_gar) print(portfolio)
方案2:定向生成法(效率更高,适合超大样本量场景)
针对你当前5选4的场景,合法样本本质只有两类:排除RO、或者排除SI。可以直接按权重计算两类样本的抽样概率,定向生成合法样本,避免无效抽样:
import numpy as np cities = ['RO', 'MI', 'VE', 'NA', 'SI'] cities_prob = [0.2, 0.2, 0.2, 0.2, 0.2] np.random.seed(42) portfolio = [] sample_count = 10000 # 计算排除RO的组合权重、排除SI的组合权重 weight_exclude_ro = np.prod([cities_prob[cities.index(c)] for c in ['MI', 'VE', 'NA', 'SI']]) weight_exclude_si = np.prod([cities_prob[cities.index(c)] for c in ['RO', 'MI', 'VE', 'NA']]) total_weight = weight_exclude_ro + weight_exclude_si prob_exclude_ro = weight_exclude_ro / total_weight for _ in range(sample_count): if np.random.rand() < prob_exclude_ro: # 排除RO,生成样本 port = ['MI', 'VE', 'NA', 'SI'] else: # 排除SI,生成样本 port = ['RO', 'MI', 'VE', 'NA'] # 如果需要打乱元素顺序可以取消下一行的注释 # np.random.shuffle(port) portfolio.append(port) print(portfolio)
注意事项
- 如果后续你需要扩展互斥规则、或者修改抽样大小/城市数量,优先使用方案1,仅需修改
if判断的校验规则即可,适配性更强 - 如果需要保留原始抽样的元素随机顺序,方案1无需额外调整,方案2需要补充打乱顺序的逻辑
内容的提问来源于stack exchange,提问作者Adorable
相关产品推荐
相关产品推荐

