Python中的重复抽样

10

我有一个包含大约50个元素的字符串,我需要对其进行随机排序并生成一个更长的字符串,我发现random.sample()只能选择唯一的元素,这很好但不适合我的用途,是否有一种方法可以在Python中允许重复元素,或者我需要手动构建一个循环呢?


为什么 random.sample() 不完全符合你的要求? - Anton vBR
@AntonvBR 它选择唯一的元素,因此如果我的列表长度为K,而我需要任何大于K的数字,它会给出一个错误,不允许重复。 - S. W. G.
1
如果提供的答案中有一个适用于您,请将其标记为已接受。 - Engineero
1
有人能解释一下为什么它实际上被称为“有放回抽样”而不是“重复抽样”吗? - scarface
4个回答

18
你可以使用 numpy.random.choice。它有一个参数来指定你想要的样本数量,还有一个参数来指定是否需要替换。以下类似这样的东西应该可以工作。
import numpy as np
choices = np.random.choice([1, 2, 3], size=10, replace=True)
# array([2, 1, 2, 3, 3, 1, 2, 2, 3, 2])
如果您的输入是字符串,比如说my_string = 'abc',您可以使用以下代码:
choices = np.random.choice([char for char in my_string], size=10, replace=True)
# array(['c', 'b', 'b', 'c', 'b', 'a', 'a', 'a', 'c', 'c'], dtype='<U1')

然后通过以下方式获取一个新的字符串:

new_string = ''.join(choices)
# 'cbbcbaaacc'

性能

计时三个答案和评论中的random.choices(跳过''.join部分,因为我们都使用了它),从字符串'abc'生成1000个样本,得到:

  • numpy.random.choice([char for char in 'abc'], size=1000, replace=True)

    34.1 µs ± 213 ns每个循环(7个运行的平均值±标准偏差,每个循环10000次)

  • random.choices('abc', k=1000)

    269 µs ± 4.27 µs每个循环(7个运行的平均值±标准偏差,每个循环1000次)

  • [random.choice('abc') for _ in range(1000)]

    924 µs ± 10.4 µs每个循环(7个运行的平均值±标准偏差,每个循环1000次)

  • [random.sample('abc',1)[0] for _ in range(1000)]

    4.32 ms ± 67.3 µs每个循环(7个运行的平均值±标准偏差,每个循环100次)

Numpy远远是最快的。如果你在那里放置''.join部分,你实际上会看到numpy和random.choices不分上下,在这个例子中都比下一个最快的快三倍。


你测试过random.choices函数并使用k参数指定长度了吗? - S. W. G.
1
我使用 random.choices([char for char in 'abc'], k=1000) 的每个循环时间为 269 us +/- 6.43 us。但是,Numpy仍然是最快的。 - Engineero
你是如何测量所花费的时间的?replace参数是什么意思? - S. W. G.
1
@S.Redrum 我使用Jupyter笔记本中的@timeit宏测量了所花费的时间。它自动运行相同命令的一堆迭代,并提供计时统计信息。replace参数只是意味着它会重复采样,因此在采样时不会用尽列表。也就是说,元素可以重复。 - Engineero

0
你可以像这样做:
import random
dict = 'abcdef'
''.join([random.choice(dict) for x in range(50)])

0

不是说这是最有效的(你应该在这里使用choice)...但考虑一下:

import random
a = ['a','b','c']
' '.join([random.sample(a,1)[0] for _ in range(6)])

0

我找到了这个,我忘记提到我使用的是Python 3.6:

DICTIONARY_NUMBERS_HEX = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
block_text = "".join(random.choices(DICTIONARY_NUMBERS_HEX,k=50)

使用k=50命名参数将生成重复元素。


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