【问题标题】:how to pick a value from a list where the number in the list is its % chance of being picked如何从列表中选择一个值,其中列表中的数字是其被选择的百分比
【发布时间】:2021-05-09 06:11:40
【问题描述】:

基本,我有一个这样的列表: Thislist = [20, 34, 46]

我想要这样,所以当随机选择一个数字时,第一个数字将有 20% 的机会被选中, 第二个号码将有 34% 的机会被选中, 第 3 个号码有 46% 的几率被选中。

【问题讨论】:

  • 您希望选择的数字是{20, 34, 46} 集合之一,还是该列表只是您希望应用于某个other 列表的权重?换句话说,您是否要从例如[1, 2, 3] 中选择一个具有百分比权重[20, 34, 46] 的数字?如果权重加起来不等于 100,你想做什么?
  • 抱歉,澄清一下,您必须假设列表总是不同的,并且长度不同。
  • {20, 34, 46} 我们是否应该计算 [20, 34, 46] 的权重,我也有适当的数学来确保它增加到 100
  • 好的,我正在努力想一个用例,但至少我现在明白了 :-)
  • 对于任何想知道我在做什么的人,我正在做这样的事情:youtube.com/watch?v=9zfeTw-uFCw 但是,问题已经解决了,汉克斯!

标签: python list random


【解决方案1】:

只要数字是加到 100 的整数,那么可能最简单的方法是创建一个列表,其中每个数字在其中重复多次,然后从该列表中随机选择。

import random

Thislist = [20, 34, 46]
l = [n for v in Thislist for n in [v] * v]
print(random.choice(l))

示例测试代码:

res = {}
for _ in range(1000000):
    c = random.choice(l)
    res[c] = res.get(c, 0) + 1
    
print(res)

样本输出:

{46: 459771, 20: 200242, 34: 339987}

关于性能的说明。

在形成l 列表时显然存在设置成本。如果仅从列表中进行一些选择,@TharunK 的答案会更有效。然而,除了这个小数字之外,random.choice 的速度比random.choices 快得多(我的测试大约是我的 4 倍),从而使这个解决方案更加高效。

【讨论】:

  • 我要测试一下,brb
  • @Scott,我认为没关系,它只是创建了一个包含 20 个 20、34 个 34 等的扁平列表。
  • 可能有比从[12345, 67890, 99999999999999] 构建大量列表更好的方法,但是,由于 OP 表示它的总和为 100,所以这里不用担心。
  • @paxdiablo 是的,我认为在这种情况下,Tharun 的回答会更好
  • Tharun 的答案是真正正确的答案。关键是,您可以从任何(正)分布中生成(加起来无关紧要)。您首先必须将每个条目除以总积分(最后是 bin 宽度),然后得到一个归一化的(到一个)PDF(概率密度函数)。可以通过CDF(y)=integrate(-inf,y) PDF(x) dx得到CDF(累积密度函数),然后在(0,1]中生成一个统一的随机数R,逆得到正确的数CDF:x_random = CDF^{-1} (R).random.choices() 正在为您执行此操作。
【解决方案2】:

您可以使用random.choices()

例子

import random
    
num = [20, 34, 46]
for i in range(10):
    item = random.choices(num,num)
    print("Iteration:", i, "Weighted Random choice is", item[0])

参考: https://docs.python.org/3/library/random.html#random.choices

【讨论】:

  • 为什么要重复列表?你可以做random.choices(num, num) 来为两个参数使用相同的列表。 (k 默认为 1。)
  • 因为 OP 只是给出了一个示例列表,所以列表不必是权重,因为它是元素
  • 尼克,我明白你和山姆想告诉我什么,但是如果列表不是权重怎么办,例如:如果列表是 num = [1,2,3,4,5,6] 而概率是 weights = (10,20,30,10,10,20)
  • Tharun,根据添加到问题中以响应我的查询的 cmets,看起来列表和权重 始终相同。
  • 哦,对了,当我回答这个问题时,cmets 不在那里
【解决方案3】:

这是一个例子

import random
Thislist = [num for n in [[20]*20,[34]*34,[46]*46] for num in n]
print(random.choice(Thislist))

【讨论】:

  • @Dion 无论如何,一般来说你不应该编辑其他人的答案,尤其是不要添加代码。在这种情况下,您应该添加自己的答案。见meta.stackoverflow.com/questions/260245/…
  • @Nick 抱歉,以后会注意的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-01
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
  • 1970-01-01
相关资源
最近更新 更多