25

是否可以修改 numpy.random.choice 函数以使其返回所选元素的索引?基本上,我想创建一个列表并随机选择元素而不替换

import numpy as np
>>> a = [1,4,1,3,3,2,1,4]
>>> np.random.choice(a)
>>> 4
>>> a
>>> [1,4,1,3,3,2,1,4]

a.remove(np.random.choice(a))将删除具有它遇到的值的列表的第一个元素(a[1]在上面的示例中),它可能不是选择的元素(例如,a[7])。

4

8 回答 8

15

这是找出随机选择元素的索引的一种方法:

import random # plain random module, not numpy's
random.choice(list(enumerate(a)))[0]
=> 4      # just an example, index is 4

或者您可以在一个步骤中检索元素和索引:

random.choice(list(enumerate(a)))
=> (1, 4) # just an example, index is 1 and element is 4
于 2013-09-13T20:08:02.270 回答
13

关于您的第一个问题,您可以反过来,从数组的索引中随机选择,a然后获取值。

>>> a = [1,4,1,3,3,2,1,4]
>>> a = np.array(a)
>>> random.choice(arange(a.size))
6
>>> a[6]

但是,如果您只需要随机样本而无需更换,replace=False就可以了。不记得是什么时候第一次添加的random.choice,可能是 1.7.0。因此,如果您运行得非常老numpy,它可能无法正常工作。请记住,默认值为replace=True

于 2013-09-13T20:24:26.110 回答
9
numpy.random.choice(a, size=however_many, replace=False)

如果您想要一个无需更换的样品,只需让 numpy 为您制作一个。不要重复循环和绘制项目。这将产生臃肿的代码和糟糕的性能。

例子:

>>> a = numpy.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> numpy.random.choice(a, size=5, replace=False)
array([7, 5, 8, 6, 2])

在足够新的 NumPy(至少 1.17)上,您应该使用新的随机性 API,它修复了长期存在的性能问题,即旧 API 的replace=False代码路径不必要地在后台生成了输入的完整排列:

rng = numpy.random.default_rng()
result = rng.choice(a, size=however_many, replace=False)
于 2013-09-13T20:08:53.400 回答
4

与其他答案相比,这有点偏左,但我认为这可能有助于你在更大程度上尝试做的事情。您可以通过改组源数组中元素的索引来生成随机样本而无需替换:

source = np.random.randint(0, 100, size=100) # generate a set to sample from
idx = np.arange(len(source))
np.random.shuffle(idx)
subsample = source[idx[:10]]

这将通过从源集(这里,大小为 100)中绘制元素而不进行替换来创建一个样本(这里,大小为 10)。

您可以使用剩余的索引值与未选择的元素进行交互,即:

notsampled = source[idx[10:]]
于 2013-09-13T20:40:40.333 回答
1

而不是使用choice,您也可以简单地使用random.shuffle您的数组,即

random.shuffle(a)  # will shuffle a in-place
于 2016-12-02T13:40:21.577 回答
1

也许晚了,但值得一提的是这个解决方案,因为我认为最简单的方法是:

a = [1, 4, 1, 3, 3, 2, 1, 4]
n = len(a)
idx = np.random.choice(list(range(n)), p=np.ones(n)/n)

这意味着您正在从索引中统一选择。在更一般的情况下,您可以通过以下方式进行加权采样(并返回索引):

probs = [.3, .4, .2, 0, .1]
n = len(a)
idx = np.random.choice(list(range(n)), p=probs)

如果您尝试这样做很多次(例如 1e5),则所选索引的直方图会像[0.30126 0.39817 0.19986 0. 0.10071]在这种情况下一样,这是正确的。

无论如何,您应该从索引中选择并使用值(如果需要)作为它们的概率。

于 2019-11-27T15:00:11.230 回答
0

根据您的评论:

样品已经a. 我想直接使用,a以便我可以控制还剩下多少元素并使用a. – 快乐派

在我看来,您在删除随机选择的元素a后有兴趣使用它。n相反,为什么不使用N = len(a) - n随机选择的元素a?由于您希望它们仍保持原始顺序,因此您可以从@CTZhu 答案中的索引中进行选择,然后对它们进行排序并从原始列表中获取:

import numpy as np
n = 3 #number to 'remove'
a = np.array([1,4,1,3,3,2,1,4])
i = np.random.choice(np.arange(a.size), a.size-n, replace=False)
i.sort()
a[i]
#array([1, 4, 1, 3, 1])

所以现在你可以a再次保存它:

a = a[i]

并使用删除a的元素。n

于 2013-09-13T20:39:55.910 回答
0

这是一个简单的解决方案,只需从范围函数中选择即可。

import numpy as np
a = [100,400,100,300,300,200,100,400]
I=np.random.choice(np.arange(len(a)))
print('index is '+str(I)+' number is '+str(a[I]))
于 2019-08-14T19:53:26.500 回答