随机整数并不总是遵循均匀分布

67

我在使用Python中的随机库模拟我正在工作的项目时做了一些尝试,但是发现自己处于一个非常奇怪的位置。

假设我们有以下Python代码:

from random import randint
import seaborn as sns

a = []
for i in range(1000000):
    a.append(randint(1,150))

sns.distplot(a)

这个图形的数据应该遵循“离散均匀”分布。

1到150之间的范围

但是,当我将范围从1改为110时,图形出现了多个峰值。

from random import randint
import seaborn as sns

a = []
for i in range(1000000):
    a.append(randint(1,110))

sns.distplot(a)

1到110的范围

我的印象是峰值在0、10、20、30等位置,但我无法解释它。

编辑:我的问题与提出的重复问题不同,因为我遇到的问题是seaborn库和我可视化数据的方式。

编辑2:根据答案的建议,我尝试通过更改seaborn库来验证它。使用matplotlib进行绘图后两个图形都是相同的。

from random import randint
import matplotlib.pyplot as plt

a = []
for i in range(1000000):
    a.append(randint(1,110))

plt.hist(a) 

来自matplotlib


可能是Python的random.randint是否具有统计随机性?的重复问题。 - ChatterOne
5
从你叠加的核密度图中,你应该能够看出峰值并不是真实存在的。 - Matthew Drury
1
现在你可以解决这个谜题:https://ericlippert.com/2012/02/24/a-simple-puzzle/ - Eric Lippert
@EricLippert 现在如果我们能让.NET团队修复System.Random中的等效bug就好了... - CodesInChaos
2个回答

128
你的问题似乎出在你的图形绘制库seaborn上,而不是randint()函数。
根据我的计数,你的seaborn分布图中有50个箱子。看起来seaborn将你返回的randint()值放入这些箱子中,而没有办法让110个值均匀地分布到50个箱子中。因此,你会得到那些顶峰,其中三个值被放入一个箱子,而其他箱子只含有两个值。顶峰的值证实了这一点:它们比其他条形图的高度高出50%,符合3个值的箱子,而不是2个值的箱子的预期高度。
另一种方法是强制seaborn使用55个箱子来绘制这110个值(或者使用10个箱子或110的其他因子)。如果你仍然看到顶峰,那么你就要考虑randint()函数是否存在问题了。

14
当某件事情显而易见,但你却视而不见时,现在完全明白了。感谢你的回答。等时间限制结束后我会接受它 :) - Tasos
5
我们都有忽略显而易见的时刻:我肯定也有!你不用客气。 - Rory Daulton

21

在 @RoryDaulton 的出色回答中,我运行了 randint(1:110),生成一个频率计数,并将其转换为 R 向量的计数,如下所示:

hits = {i:0 for i in range(1,111)}
for i in range(1000000): hits[randint(1,110)] += 1
hits = [hits[i] for i in range(1,111)]
s = 'c('+','.join(str(x) for x in hits)+')'
print(s)

c(9123,9067,9124,8898,9193,9077,9155,9042,9112,9015,8949,9139,9064,9152,8848,9167,9077,9122,9025,9159,9109,9015,9265,9026,9115,9169,9110,9364,9042,9238,9079,9032,9134,9186,9085,9196,9217,9195,9027,9003,9190,9159,9006,9069,9222,9205,8952,9106,9041,9019,8999,9085,9054,9119,9114,9085,9123,8951,9023,9292,8900,9064,9046,9054,9034,9088,9002,8780,9098,9157,9130,9084,9097,8990,9194,9019,9046,9087,9100,9017,9203,9182,9165,9113,9041,9138,9162,9024,9133,9159,9197,9168,9105,9146,8991,9045,9155,8986,9091,9000,9077,9117,9134,9143,9067,9168,9047,9166,9017,8944)

接着我把这个内容粘贴到了 R 控制台,重构了观测数据,并对结果使用了 R 的 hist() 函数,得到了下面这个直方图(上面叠加了密度曲线):

enter image description here

正如您所看到的,这证实了您观察到的问题并非源自于 randint,而是来自于 sns.displot() 所造成的人为因素。


1
我在直方图中计算了22个条,当然22是110的除数。感谢确认并阐述我的答案的一部分。 - Rory Daulton
@RoryDaulton 对于22的观察很好。我调整了直方图,现在它是一个概率直方图,上面叠加了密度,因此更接近OP的操作。 - John Coleman
你可以使用hist(x,breaks=seq(0,110,by=2.2))来获得类似于seaborn图的效果。有趣的是,直接要求50个bin并不能产生相同的效果。 - James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接