有无放回的抽样
了解有放回抽样和无放回抽样之间的区别很重要。假设我们有一袋 1 颗蓝色和 2 颗红色弹珠,您选择了 2 颗弹珠。如果您在拉出第一个弹珠后将弹珠放回原位,则可能会得到 2 个蓝色弹珠。这叫做抽样和替代品。使用random.choice是采样和替代品。
random.choices() 和 random.sample()
您可以使用 random 模块中的 choices() 函数提取多个元素。例如,从一袋 1 个红色和 2 个蓝色弹珠中抽取 4 个弹珠和替代品:
>>> import random
>>> marbles = ['red'] * 1 + ['blue'] * 2
>>> random.choices(marbles, k=4)
['red', 'blue', 'blue', 'blue']
您可以使用采样没有使用 sample 函数使用 random 模块进行替换:
>>> random.sample(marbles, 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/homebrew/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/random.py", line 482, in sample
raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative
正如预期的那样,这给出了一个错误。你不能从一袋 3 颗弹珠中取出 4 颗弹珠。现在如果我们在袋子里放 1000 颗红色弹珠和 2000 颗蓝色弹珠,我们会得到:
>>> marbles = ['red'] * 1000 + ['blue'] * 2000
>>> random.sample(marbles, 4)
['blue', 'blue', 'blue', 'red']
内存使用和权重
上面示例的一个可能问题是,如果弹珠较多,则需要大量内存。因此,choice()函数有一个weights参数。你可以像这样使用它:
>>> marbles = ['red', 'blue']
>>> weights = [1000, 2000]
>>> random.choices(marbles, weights=weights, k=4)
['blue', 'blue', 'blue', 'red']
遗憾的是,random 模块没有使用权重进行不替换采样的功能。
使用 for 循环重复采样
最后,我们需要计算结果。一种更高级的方法是使用字典和 collections 模块中的 defaultdict。作为替代方案,我们将创建一个结果列表,并使用该列表的一组循环遍历不同的结果。
随机导入
样本大小 = 4
重复采样 = 100
outcomes = []
marbles = ['red'] * 5000 + ['blue'] * 5000
for i in range(REPEAT_SAMPLING):
outcome = ', '.join(random.sample(marbles, SAMPLE_SIZE))
outcomes.append(outcome)
for outcome in set(outcomes):
print(f'{outcome} appeared {outcomes.count(outcome)} times out of {REPEAT_SAMPLING}')