You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何实现元组列表带权重无放回的随机子集抽取?

加权无放回抽样实现方案

你需要的带权重无放回抽样可以通过以下三种方法实现,全部支持元组列表作为输入:

方案1:Python 3.9+ 原生实现(最优方案)

Python 3.9及以上版本的random.sample接口已经原生支持weights加权参数,无需额外依赖,也不限制输入元素类型:

import random

# 示例待选元组列表,可直接替换为你的实际数据
item_list = [("red", 10), ("orange", 10), ("blue", 10), ("yellow", 10), ("green", 50)]
# 提取对应权重,也可以直接写独立的权重列表
weights = [i[1] for i in item_list]

# 无放回抽取3个元素,自动遵循权重概率
selected = random.sample(item_list, k=3, weights=weights)
print(selected)

方案2:低版本Python兼容实现

如果使用3.9以下版本的Python,可以手动实现加权抽样逻辑,每次抽取一个元素后从待选池移除该元素及其权重,直到抽够目标数量:

import random
from itertools import accumulate
import bisect

def weighted_sample(population, weights, k):
    # 复制原数据避免修改原列表
    pop_copy = population.copy()
    weight_copy = weights.copy()
    res = []
    for _ in range(k):
        cum_weights = list(accumulate(weight_copy))
        total = cum_weights[-1]
        # 按权重随机选中对应索引
        idx = bisect.bisect_left(cum_weights, random.uniform(0, total))
        res.append(pop_copy.pop(idx))
        weight_copy.pop(idx)
    return res

# 调用示例
item_list = [("red", 10), ("orange", 10), ("blue", 10), ("yellow", 10), ("green", 50)]
weights = [i[1] for i in item_list]
print(weighted_sample(item_list, weights, 3))

方案3:Numpy实现(适配已有numpy依赖的项目)

你提到的numpy.random.choice无法直接传入元组列表的问题可以通过抽索引的方式解决:

import numpy as np

item_list = [("red", 10), ("orange", 10), ("blue", 10), ("yellow", 10), ("green", 50)]
# 权重需要归一化到和为1
weights = np.array([i[1] for i in item_list], dtype=np.float64)
weights /= weights.sum()

# 先对索引做无放回加权抽样
selected_idx = np.random.choice(len(item_list), size=3, replace=False, p=weights)
# 按索引取对应元组
selected = [item_list[i] for i in selected_idx]
print(selected)

内容的提问来源于stack exchange,提问作者Nikki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 07:48:01