所以我写了一个简短的Python函数来绘制骰子实验的分布结果。它运行得很好,但是当我运行例如 dice(1,5000)
或 dice(10,5000)
或 dice(100,5000)
直方图显示出倾斜分布(高度偏重于6)。然而,平均数显示的是即将到来的预期值,约为6。3.5
. 我想这可能与随机数的产生有关,所以我尝试了2种方法:第一种是用 random.randint
和第2个是代码中的。但是,它们的结果是相似的。好像是上限有问题。但我不知道为什么会有这样的倾斜分布。
import matplotlib.pyplot as plt
import numpy as np
import random
# Throw a dice
def dice(N,n):
result = np.zeros((n,N))
'''
N: number of dices
n: number of experiment
'''
for i in range(n):
for j in range(N):
random_number = random.random()
outcome = int(random_number * 6 + 1)
result[i][j]=outcome
laverage = np.mean(result)
print('Result of throwing %d dice(s) for %d times:'%(N,n),result)
print(laverage)
plt.hist(np.resize(result,(N*n,1)),bins=[x for x in range(1,7)])
plt.xlabel('Outcome')
plt.ylabel('Number of occurences')
plt.show()
dice(1,5000)
根据您的代码样本,问题是绘图问题,而不是计算问题,这就是为什么您看到的是正确的平均值。正如你所看到的,下图显示了五个条形图,最后一个是其他条形图的两倍。
还请注意,这些条形图是标在左边的,因此没有 "6 "条。这与以下几点有关 plt.hist
手段 bins
:
如果: 箱子 是一个序列,它定义了料仓的边缘,包括第一个料仓的左边缘和最后一个料仓的右边缘;在这种情况下,料仓可能是不等距的。除了最后一个(最右端)bin之外,所有bin都是半开的。
因此,要指定料仓边缘,你可能需要更多的东西,如
plt.hist(np.ravel(result), bins=np.arange(0.5, 7.5, 1))
而结果呢?
未问的问题
如果你想模拟 N * n
数据点,你可以直接使用numpy。替换你原来初始化的 result
和 for
循环中的任何一行。
result = (np.random.uniform(size=(n, N)) * 6 + 1).astype(int)
result = np.random.uniform(1.0. 7.0, size=(n, N)).astype(int)
result = np.random.randint(1, 7, size=(n, N))
最后一行从效率和精度上来说是比较好的。
另一个可能的改进是如何计算直方图。现在,您使用的是 plt.hist
,这就要求 np.histogram
和 plt.bar
. 对于像你这样的小整数。np.bincount
可以说是一种更好的分层技术。
count = np.bincount(result.ravel())[1:]
plt.bar(np.arange(1, 7), count)
请注意,这也简化了绘图,因为你直接指定了条形图的中心,而不是要用 plt.hist
为你猜测。
如果你很懒(比如我),你也可以用numpy直接生成一个矩阵和 海底 为你处理垃圾箱。
import numpy as np
import seaborn as sns
dices = 1000
throws = 5000
x = np.random.randint(6, size=(dices, throws)) + 1
sns.distplot(x)
哪些给。
Seaborn通常会做出很好的选择,这可以节省一些配置的时间。这至少值得一试。你也可以使用 kde=False
选项来消除密度估计。
只是为了展示seaborn的表现,同样的,100个骰子的总和也是如此。
dices = 100
throws = 5000
x = np.random.randint(6, size=(dices, throws)) + 1
sns.distplot(x.sum(axis=0), kde=False)