当需要抽样的数量多于样本数量时,不放回地随机抽样
Random sampling without replacement when more needs to be sampled than there are samples
我需要从数字列表中生成样本,在这种情况下,我可能需要采样比我拥有的更多的数字。更明确地说,这是我需要做的:
令我列表中的元素总数为N。
我需要从这个列表 M 个样本中随机抽样而不放回。
如果M <= N,那么直接使用Numpy的random.choice,不用替换。
如果M > N,则样本必须包含X乘以列表中所有N个数,其中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 <= N。
感谢您的帮助!
我会像这样包装 numpy 的 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]
编辑:不需要检查长度。当请求超过列表的长度时,您使用的算法也适用于这种情况。
你可以concatenate
the results of repeat
and random.choice
:
np.concatenate((np.repeat(L, M // len(L)), np.random.choice(L, M - M // len(L))))
首先,根据需要重复序列,然后选择所需的剩余数量;最后,将两个数组连接起来。
请注意,您可以使用 replace
parameter:
轻松确定 choice
是否可以替换或不替换
replace : boolean, optional --
Whether the sample is with or without replacement
下面是情况下 0 < M-N < 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])
使用divmod()
获取列表的重复次数和remainder/shortfall。然后可以使用 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')
我需要从数字列表中生成样本,在这种情况下,我可能需要采样比我拥有的更多的数字。更明确地说,这是我需要做的:
令我列表中的元素总数为N。
我需要从这个列表 M 个样本中随机抽样而不放回。
如果M <= N,那么直接使用Numpy的random.choice,不用替换。
如果M > N,则样本必须包含X乘以列表中所有N个数,其中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 <= N。
感谢您的帮助!
我会像这样包装 numpy 的 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]
编辑:不需要检查长度。当请求超过列表的长度时,您使用的算法也适用于这种情况。
你可以concatenate
the results of repeat
and random.choice
:
np.concatenate((np.repeat(L, M // len(L)), np.random.choice(L, M - M // len(L))))
首先,根据需要重复序列,然后选择所需的剩余数量;最后,将两个数组连接起来。
请注意,您可以使用 replace
parameter:
choice
是否可以替换或不替换
replace : boolean, optional -- Whether the sample is with or without replacement
下面是情况下 0 < M-N < 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])
使用divmod()
获取列表的重复次数和remainder/shortfall。然后可以使用 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')