【问题标题】:How to make sure that a list of generated numbers follow a uniform distribution如何确保生成的数字列表遵循均匀分布
【发布时间】:2020-06-13 09:17:08
【问题描述】:

我有一个从 0 到 149 的 150 个数字的列表。我想使用具有 150 次迭代的 for 循环来生成 150 个 6 个数字的列表,这样,t 在每次迭代中 k,数字 @987654324 @ 包括 5 个不同的随机数。例如:

S0 = [0, r1, r2, r3, r4, r5] # r1, r2,..., r5 are random numbers between 0 and 150
S1 = [1, r1', r2', r3', r4', r5'] # r1', r2',..., r5' are new random numbers between 0 and 150
...
S149 = [149, r1'', r2'', r3'', r4'', r5''] 

此外,每个列表中的数字必须不同,并且最小距离为 5。这是我正在使用的代码:

import random
import numpy as np

final_list = []
for k in range(150):
    S = [k]
    for it in range(5):
        domain = [ele for ele in range(150) if ele not in S]
        d = 0
        x = k
        while d < 5:
            d = np.Infinity
            x = random.sample(domain, 1)[0]
            for ch in S:
                if np.abs(ch - x) < d:
                    d = np.abs(ch - x)
        S.append(x)
    final_list.append(S)

输出:

[[0, 149, 32, 52, 39, 126],
 [1, 63, 16, 50, 141, 79],
 [2, 62, 21, 42, 35, 71],
...
 [147, 73, 38, 115, 82, 47],
 [148, 5, 78, 115, 140, 43],
 [149, 36, 3, 15, 99, 23]]

现在,代码正在运行,但我想知道是否可以强制每个数字在所有迭代中的重复次数大致相同。例如,使用前面的代码后,该图表示每个数字在生成的列表中出现的次数:

如您所见,有些数字出现了 10 次以上,而有些数字只出现了 2 次。是否可以减少这种变化水平,以便可以将该图近似为均匀分布?谢谢。

【问题讨论】:

    标签: python random uniform-distribution


    【解决方案1】:

    首先,我不确定您关于当前结果不是均匀分布的断言是否一定正确。对我来说,尝试检查多次重复该过程的直方图似乎是谨慎的做法,而不仅仅是一次。

    我不是统计学家,但是当我想近似均匀分布时(并假设random 中的函数提供均匀分布),我尝试做的只是简单地接受random 函数返回的所有结果。为此,我需要在调用这些函数之前限制它们的选择。我会这样处理你的任务:

    import random
    import numpy as np
    
    N = 150
    
    def random_subset(n):
        result = []
        cands = set(range(N))
        for i in range(6):
            result.append(n)                  # Initially, n is the number that must appear in the result
            cands -= set(range(n - 4, n + 5)) # Remove candidates less than 5 away 
            n = random.choice(list(cands))    # Select next number
        return result
    
    result = np.array([random_subset(n) for n in range(N)])
    print(result)
    

    简单地说,每当我在结果集中添加一个数字n时,我都会从选择候选中取出一个适当大小的环境,以确保在结果集中不能选择距离小于5的数字未来。

    代码未优化(多次setlist 转换),但它可以工作(根据我的理解)。

    【讨论】:

    • 你的代码比我的好,谢谢。你是对的,我不能断言我的分布不均匀,只使用一次迭代,但事实证明我的目标是只使用一两次迭代来降低变异水平,因为我不能使用更多。
    【解决方案2】:

    如果你愿意,你可以强制它完全一致。

    为混合使用全局变量和本地变量道歉,这似乎是最易读的。您可能希望根据常量的可变性进行重写 =)

    import random
    
    SIZE = 150
    SAMPLES = 5
    
    def get_samples():
        pool = list(range(SIZE)) * SAMPLES
        random.shuffle(pool)
        items = []
        for i in range(SIZE):
            selection, pool = pool[:SAMPLES], pool[SAMPLES:]
            item = [i] + selection
            items.append(item)
        return items
    

    然后你将恰好有 5 个(并且还有一个处于领先位置,这是一种奇怪的数据结构)。

    >>> set(collections.Counter(vv for v in get_samples() for vv in v).values())                                                                      
    {6}
    

    上述方法并不能保证最后 5 个数字是唯一的,事实上,您可能希望 ~10/150 有重复。如果这很重要,您需要进一步过滤您的分布,并确定您对紧密一致性、重复等的重视程度。

    如果您的数字与您上面给出的大致相同,您也可以(相当)修补结果并希望避免长时间的搜索(SAMPLES 尺寸接近OPTIONS 尺寸的情况并非如此)

    def get_samples():
        pool = list(range(SIZE)) * SAMPLES
        random.shuffle(pool)
        i = 0
        while i < len(pool):
            if i % SAMPLES == 0:
                seen = set()
            v = pool[i]
            if v in seen:  # swap
                dst = random.choice(range(SIZE))
                pool[dst], pool[i] = pool[i], pool[dst]
                i = dst - dst % SAMPLES  # Restart from swapped segment
            else:
                seen.add(v)
                i += 1
        items = []
        for i in range(SIZE):
            selection, pool = pool[:SAMPLES], pool[SAMPLES:]
            assert len(set(selection)) == SAMPLES, selection
            item = [i] + selection
            items.append(item)
        return items
    

    这通常需要不到 5 次通过来清理任何重复项,并且应该使所有安排都同样可能满足您的条件。

    【讨论】:

      猜你喜欢
      • 2017-04-27
      • 2019-02-22
      • 2021-09-19
      • 1970-01-01
      • 2016-11-17
      • 1970-01-01
      • 1970-01-01
      • 2014-09-06
      • 2021-02-10
      相关资源
      最近更新 更多