从列表中创建分布并生成随机数,这些数字遵循Python中的分布

时间:2015-01-20 23:29:33

标签: python random distribution

假设我有一个数字列表(在这个特定的例子中,所有数字都在0.5到1.5之间,当然它是一个离散的集合)。

my_list=  [0.564, 1.058, 0.779, 1.281, 0.656, 0.863, 0.958, 1.146, 0.742, 1.139, 0.957, 0.548, 0.572, 1.204, 0.868, 0.57, 1.456, 0.586, 0.718, 0.966, 0.625, 0.951, 0.766, 1.458, 0.83, 1.25, 0.7, 1.334, 1.015, 1.43, 1.376, 0.942, 1.252, 1.441, 0.795, 1.25, 0.851, 1.383, 0.969, 0.629, 1.008, 0.729, 0.841, 0.619, 0.63, 1.189, 0.514, 0.899, 0.807, 0.63, 1.101, 0.528, 1.385, 0.838, 0.538, 1.364, 0.702, 1.129, 0.639, 0.557, 1.28, 0.664, 1.021, 1.43, 0.792, 1.229, 0.837, 1.183, 0.54, 0.831, 1.279, 1.385, 1.377, 0.827, 1.32, 0.537, 1.19, 1.446, 1.222, 0.762, 1.302, 0.626, 1.352, 1.316, 1.286, 1.239, 1.027, 1.198, 0.961, 0.515, 0.989, 0.979, 1.123, 0.889, 1.484, 0.734, 0.718, 0.758, 0.782, 1.163, 0.579, 0.744, 0.711, 1.13, 0.598, 0.913, 1.305, 0.684, 1.108, 1.373, 0.945, 0.837, 1.129, 1.005, 1.447, 1.393, 1.493, 1.262, 0.73, 1.232, 0.838, 1.319, 0.971, 1.234, 0.738, 1.418, 1.397, 0.927, 1.309, 0.784, 1.232, 1.454, 1.387, 0.851, 1.132, 0.958, 1.467, 1.41, 1.359, 0.529, 1.139, 1.438, 0.672, 0.756, 1.356, 0.736, 1.436, 1.414, 0.921, 0.669, 1.21, 1.041, 0.597, 0.541, 1.162, 1.292, 0.538, 1.011, 0.828, 1.356, 0.897, 0.831, 1.018, 1.412, 1.363, 1.371, 1.231, 1.278, 0.564, 1.134, 1.324, 0.593, 1.307, 0.66, 1.376, 1.469, 1.315, 0.959, 1.099, 1.313, 1.032, 1.128, 1.175, 0.64, 0.581, 1.09, 0.934, 0.698, 1.272]

我可以将它作为直方图分布图

hist(my_list, bins=20, range=[0.5,1.5])
show()

产生enter image description here

现在,我想创建另一个随机数列表(假设这个新列表由100个数字组成),它们将遵循相同的分布(不确定如何将离散集链接到连续分布!!!)旧列表(my_list),所以如果我从新列表中绘制直方图分布,它将基本上产生相同的直方图分布。

在Python 2.7中有没有办法这样做?我提前感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

您首先需要“了解”感兴趣的范围,当然您可以使用scipy& c中的工具来完成它,但是为了理解一些Python版本可能会有什么帮助 - 为了便于理解,没有优化:

import collections

def buckets(discrete_set, amin=None, amax=None, bucket_size=None):
    if amin is None: amin=min(discrete_set)
    if amax is None: amax=min(discrete_set)
    if bucket_size is None: bucket_size = (amax-amin)/20
    def to_bucket(sample):
        if not (amin <= sample <= amax): return None  # no bucket fits
        return int((sample - amin) // bucket_size)
    b = collections.Counter(to_bucket(s)
            for s in discrete_set if to_bucket(s) is not None)
    return amin, amax, bucket_size, b

所以,现在你有一个Counter(基本上是dict)映射每个桶从0到它在离散集中观察到的计数。

接下来,您需要生成一个随机样本,该样本与通过调用buckets(discrete_set)测量的桶分布相匹配。计数器的elements方法可以提供帮助,但您需要random.sample的列表...:

mi, ma, bs, bks = buckets(discrete_set) 
buckelems = list(bks.elements())

(这可能会浪费很多空间,但您可以稍后进行优化,与这种以理解为重点的概述分开: - )。

现在很容易得到一个N大小的样本,例如:

def makesample(N, buckelems, mi, ma, bs):
    s = []
    for _ in range(N):
        buck = random.choice(buckelems)
        x = random.uniform(mi+buck*bs, mi+(buck+1)*bs)
        s.append(x)
    return s

在这里,我假设桶的细粒度足以在每个桶中使用均匀分布。

现在,优化这一点当然很有趣 - buckelems将包含最初在discrete_set中的项目,如果这会对内存造成过大负担,则可以构建和使用累积分布代替。

或者,人们可以完全绕过Counter,只是将离散集中的每个项目“舍入”到其桶的下限,如果内存正常但人们想要更快的速度。或者,可以在“扰乱”所选值之前将discrete_set单独留在random.choice中并{{1}}(以不同方式取决于确切问题的约束)。没有结束的乐趣......! - )

答案 1 :(得分:1)

当您尝试进行分配拟合时,不要过多地读取样本量较小的直方图的山谷和峰值。

我对你的数据进行了Kolmogorov-Smirnov检验,以检验它们来自统一(0.5,1.5)分布的假设,并且未能拒绝。因此,您可以生成任何您想要的大小样本(0.5,1.5)

鉴于您声明基础分布是连续的,我认为分布拟合方法优于基于直方图/桶的方法。