如何获取numpy.random.choice的索引?-蟒

how to get the index of numpy.random.choice? - python

提问人:HappyPy 提问时间:9/14/2013 更新时间:5/10/2022 访问量:54709

问:

是否可以修改 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]

python 随机 numpy

评论

2赞 Robᵩ 9/14/2013
它可能不是所选择的元素,但似乎两种情况是无法区分的。
0赞 Brian Cain 9/14/2013
enumerate可能会起作用
0赞 HappyPy 9/14/2013
@Rob:不完全是。创建列表后,无论我删除哪个元素,它都必须保持相同的顺序,这一点很重要。
1赞 Jesper - jtk.eth 11/7/2017
...应该有一个函数 np.random.argchoice(...)

答:

15赞 Óscar López 9/14/2013 #1

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

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

评论

2赞 HappyPy 9/14/2013
这对我不起作用。它给了我一个“ValueError:a 必须是一维的”
0赞 HappyPy 9/14/2013
我复制/粘贴了您的代码和上面的列表,但仍然收到相同的错误。它和你一起工作吗?
0赞 user2357112 9/14/2013
list(enumerate(a))生成一个元组列表,该表被视为类似 2D 数组的对象。这是行不通的。
0赞 Óscar López 9/14/2013
@HappyPy你是对的,我用 ,而不是 .如果你一定要绝对使用 ,那么我的答案就行不通了,我会删除它。但是,如果您使用普通的旧(来自模块),它将起作用。random.choicenp.random.choicenp.random.choicerandom.choicerandom
10赞 Russell Myers 4/7/2016
强烈警告,这将具有糟糕的性能,这是人们首先使用 numpy 的主要原因之一。您正在迭代整个数组。只生成一个介于 0 和列表长度之间的随机整数会比生成这个整数更便宜。
10赞 user2357112 9/14/2013 #2
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)

评论

0赞 HappyPy 9/14/2013
我不明白这是怎么回事。在这种情况下,“a”是什么?你能举个例子吗?
0赞 user2357112 9/14/2013
@HappyPy:与代码中的内容完全相同;它是我们想要从中获取样本的类似数组的对象。 是我们想要的样品中的元素数量,并要求提供不替换的样品。结果将是一个包含所需样品的一维形状数组。asizereplace=False(however_many,)
0赞 HappyPy 9/14/2013
示例已为“a”。我想直接使用“a”,这样我就可以控制还剩下多少元素并使用“a”执行其他操作。
0赞 user2357112 9/14/2013
@HappyPy:这听起来你用了numpy都错了。如果已经是一个随机样本,但你想在不替换的情况下从中抽取元素,那么你实际上是在从中抽取另一个随机样本。如果你真的,真的想从 中连续删除元素numpy 不太可能帮助你。aaaa
18赞 CT Zhu 9/14/2013 #3

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

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

但是,如果您只需要随机样本而不需要替换,那就可以了。不记得它是什么时候第一次添加到的,可能是 1.7.0。因此,如果您运行得很旧,它可能不起作用。请记住,默认值为replace=Falserandom.choicenumpyreplace=True

评论

0赞 askewchan 9/14/2013
在这种情况下,无需列出并从中进行选择,只需执行,除非我认为需要许多相互排斥的选择。np.random.randint(0,a.size)
2赞 CT Zhu 9/14/2013
@askwchan,对!我在想什么。 就够了。np.random.randint(0,a.size, size=size_you_want)
0赞 HappyPy 9/14/2013
@CT Zhu:我收到一个 AttributeError:“list”对象没有属性“size”
0赞 CT Zhu 9/14/2013
哦,是一个列表,而不是一个.首先将其转换为。我忘了复制 1 行。aarrayarray
1赞 CT Zhu 9/14/2013
@askwchan,哦,不。您的方法将始终变为采样并替换。HappyPy 确实需要它,所以一旦元素被采样,它就不会再采样。replace=False
0赞 askewchan 9/14/2013 #4

根据您的评论:

示例已经是 .我想直接使用 ,这样我就可以控制还剩下多少元素并使用 .– 快乐派aaa

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

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]

并使用删除的元素。an

4赞 lmjohns3 9/14/2013 #5

与其他答案相比,这有点偏左,但我认为它可能会有所帮助,听起来你正在尝试在更大的意义上做。您可以通过对源数组中元素的索引进行洗牌来生成一个随机样本,而无需替换:

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 号)中绘制元素来创建一个样本(此处为 100 号),而无需替换。

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

notsampled = source[idx[10:]]
1赞 Tobias Kienzler 12/2/2016 #6

除了使用 ,您还可以简单地 random.shuffle 您的数组,即choice

random.shuffle(a)  # will shuffle a in-place
0赞 Kernel 8/15/2019 #7

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

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]))
2赞 Mehdi Saman Booy 11/27/2019 #8

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

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]

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

0赞 Neil C. Obremski 5/10/2022 #9

问题标题与其描述略有不同。我只是想要标题问题的答案,它只从中获取一个(整数)索引。而不是上述任何一种,我决定(在numpy 1.21.6中测试)。numpy.random.choice()index = numpy.random.choice(len(array_or_whatever))

前任:

import numpy
a = [1, 2, 3, 4]
i = numpy.random.choice(len(a))

我在其他解决方案中遇到的问题是不必要的转换,这将在新对象中重新创建整个集合(慢!list

编号: https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html?highlight=choice#numpy.random.choice

文档中关于第一个参数的关键点:a

a:类一维数组或 int 如果是 ndarray,则从其元素生成随机样本。如果为 int,则生成随机样本,就好像它是 np.arange(a) 一样

由于这个问题很老了,那么我可能是出于新版本的便利性,而这些版本恰好支持我自己和 OP 想要的东西。