在需要采样的情况下,无需替换的随机抽样比样本

时间:2016-09-15 09:07:18

标签: python numpy sampling

我需要从一个数字列表中生成样本,在这种情况下,我可能会遇到需要采样的数字超过我的数据。更明确地说,这就是我需要做的事情:

  • 让列表中的元素总数为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.

感谢您的帮助!

4 个答案:

答案 0 :(得分:3)

您可以concatenate repeatrandom.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')