我正在寻找一个简单的函数,它可以根据相应的(也是指定的)概率生成指定随机值的数组。我只需要它来生成浮点值,但我不明白为什么它不能生成任何标量。我可以想到从现有函数构建这个函数的许多方法,但我想我可能只是错过了一个明显的SciPy或NumPy函数。
E.g:
>>> values = [1.1, 2.2, 3.3]
>>> probabilities = [0.2, 0.5, 0.3]
>>> print some_function(values, probabilities, size=10)
(2.2, 1.1, 3.3, 3.3, 2.2, 2.2, 1.1, 2.2, 3.3, 2.2)
注意:我找到了 scipy.stats.rv_discrete ,但我不明白它是如何运作的。具体来说,我不明白这(下面)的含义以及它应该做什么:
numargs = generic.numargs
[ <shape(s)> ] = ['Replace with resonable value', ]*numargs
如果rv_discrete是我应该使用的,你能否提供一个简单的例子和对上述“形状”陈述的解释?
答案 0 :(得分:25)
这是一个简短的,相对简单的函数,它返回加权值,它使用NumPy的digitize
,accumulate
和random_sample
。
import numpy as np
from numpy.random import random_sample
def weighted_values(values, probabilities, size):
bins = np.add.accumulate(probabilities)
return values[np.digitize(random_sample(size), bins)]
values = np.array([1.1, 2.2, 3.3])
probabilities = np.array([0.2, 0.5, 0.3])
print weighted_values(values, probabilities, 10)
#Sample output:
[ 2.2 2.2 1.1 2.2 2.2 3.3 3.3 2.2 3.3 3.3]
它的工作原理如下:
accumulate
我们创建垃圾箱。0
1
和random_sample
之间)
digitize
来查看这些数字属于哪些垃圾箱。答案 1 :(得分:15)
你正朝着一个好方向前进:内置scipy.stats.rv_discrete()
直接创建了一个离散的随机变量。以下是它的工作原理:
>>> from scipy.stats import rv_discrete
>>> values = numpy.array([1.1, 2.2, 3.3])
>>> probabilities = [0.2, 0.5, 0.3]
>>> distrib = rv_discrete(values=(range(len(values)), probabilities)) # This defines a Scipy probability distribution
>>> distrib.rvs(size=10) # 10 samples from range(len(values))
array([1, 2, 0, 2, 2, 0, 2, 1, 0, 2])
>>> values[_] # Conversion to specific discrete values (the fact that values is a NumPy array is used for the indexing)
[2.2, 3.3, 1.1, 3.3, 3.3, 1.1, 3.3, 2.2, 1.1, 3.3]
上面的分发distrib
因此会从values
列表中返回索引。
更一般地说,rv_discrete()
在其values=(…,…)
参数的第一个元素中采用一系列整数值,并在这种情况下返回这些值;无需转换为特定(浮点)值。这是一个例子:
>>> values = [10, 20, 30]
>>> probabilities = [0.2, 0.5, 0.3]
>>> distrib = rv_discrete(values=(values, probabilities))
>>> distrib.rvs(size=10)
array([20, 20, 20, 20, 20, 20, 20, 30, 20, 20])
其中(整数)输入值以所需的概率直接返回。
答案 2 :(得分:4)
您还可以使用Lea,一个专门用于离散概率分布的纯Python包。
>>> distrib = Lea.fromValFreqs((1.1,2),(2.2,5),(3.3,3))
>>> distrib
1.1 : 2/10
2.2 : 5/10
3.3 : 3/10
>>> distrib.random(10)
(2.2, 2.2, 1.1, 2.2, 2.2, 2.2, 1.1, 3.3, 1.1, 3.3)
Etvoilà!
答案 3 :(得分:3)
最简单的DIY方式是将概率总结为累积分布。 这样,您可以将单位间隔分割为长度等于原始概率的子间隔。现在在[0,1)上生成一个随机数统一,并查看它所处的间隔。