我需要从一个数字列表中生成样本,在这种情况下,我可能会遇到需要采样的数字超过我的数据。更明确地说,这就是我需要做的事情:
让列表中的元素总数为N.
我需要随机抽样而无需替换此列表中的M个样本。
如果M <= N,则只需使用Numpy的random.choice而无需替换。
如果M> N,则样本必须包含列表中所有N个数的X倍,其中X是N完全除M的次数,即X = floor(M / N),然后采样另外的M-(X * N)余数列表中的样品无需更换。
例如,让我的列表如下:
L = [1,2,3,4,5]
我需要抽样8个样本。然后,我首先对完整列表进行一次采样,并随机选择其他3个元素而无需替换,例如我的样本可能是:
Sampled_list = [1,2,3,4,5,3,5,1]
如何在Python中的计算时间方面尽可能高效地实现这样的代码?这可以在没有for循环的情况下完成吗?
目前我正在使用for循环实现此功能,但这对我的目的而言效率太低。我也尝试了Numpy的random.choice而没有替换,但后来我需要M&lt; = N.
感谢您的帮助!
答案 0 :(得分:3)
您可以concatenate
repeat
和random.choice
的结果:
np.concatenate((np.repeat(L, M // len(L)), np.random.choice(L, M - M // len(L))))
首先,根据需要重复该序列,然后选择所需的剩余数量;最后,这两个数组被连接起来。
请注意,您可以使用replace
parameter轻松确定choice
是否适用于替换或不使用
替换:布尔值,可选 - 样品是否有替换
答案 1 :(得分:2)
我会把numpy&#39; s random.choice()
包裹起来:
L = [1, 2, 3, 4, 5]
def wrap_choice(list_to_sample, no_samples):
list_size = len(list_to_sample)
takes = no_samples // list_size
samples = list_to_sample * (no_samples // list_size) + list(np.random.choice(list_to_sample, no_samples - takes * list_size))
return samples
print(wrap_choice(L, 2)) # [5, 1]
print(wrap_choice(L, 13)) # [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 3, 3, 1]
编辑:无需检查长度。当请求超过列表的长度时,您所使用的算法也适用于不是这种情况。
答案 2 :(得分:1)
这可能是案例的解决方案,其中0&lt; M-N&lt; max(L):
import numpy as np
from numpy.random import random
l = np.array([1, 2, 3, 4, 5])
rand = [ i for i in l[np.argsort(np.amax(l))[:M-N]] ]
new_l = np.concatenate(l,rand)
以下是一个例子:
l = np.array([1,2,3,4,5])
M, N = 7, len(l)
rand = [i for i in l[np.argsort(np.random(np.amax(l)))][:M-N]]
new_l = np.concatenate(l,rand)
这是输出:
new_list = np.array([1,2,3,4,5,3,4])
答案 3 :(得分:1)
使用divmod()
获取列表的重复次数和剩余/不足。然后可以使用numpy.random.choice()
从列表中随机选择不足。
import numpy as np
def get_sample(l, n):
samples, shortfall = divmod(n, len(l))
return np.concatenate((np.repeat(l, samples), np.random.choice(l, shortfall, False)))
>>> get_sample(range(100), 10)
array([91, 95, 73, 96, 18, 37, 32, 97, 4, 41])
>>> get_sample(range(10), 100)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9])
>>> get_sample([1,2,3,4], 0)
array([], dtype=int64)
>>> get_sample([1,2,3,4], 4)
array([1, 2, 3, 4])
>>> get_sample([1,2,3,4], 6)
array([1, 2, 3, 4, 4, 3])
>>> get_sample([1,2,3,4], 6)
array([1, 2, 3, 4, 3, 2])
>>> get_sample(list('test string'), 6)
array(['n', 's', 'g', 's', 't', ' '],
dtype='|S1')
>>> get_sample(np.array(list('test string')), 4)
array(['r', 't', 's', 'g'],
dtype='|S1')