我正在NumPy中编写一些建模例程,需要从NumPy数组中随机选择单元格并对它们进行一些处理。必须选择所有单元格而不进行替换(例如,一旦选择了单元格,就不能再次选择它,但必须在结尾处选择所有单元格。)
我正在从IDL过渡,在那里我可以找到一个很好的方法来做到这一点,但我认为NumPy有一个很好的方法来做到这一点。你会建议什么?
更新:我应该说我正在尝试在2D数组上执行此操作,因此会返回一组2D索引。
答案 0 :(得分:20)
如果您还需要原始数组,请使用numpy.random.shuffle
或numpy.random.permutation
怎么样?
如果需要就地更改数组,则可以创建如下的索引数组:
your_array = <some numpy array>
index_array = numpy.arange(your_array.size)
numpy.random.shuffle(index_array)
print your_array[index_array[:10]]
答案 1 :(得分:3)
所有这些答案对我来说似乎有点费解。
我假设你有一个多维数组,你想从中生成一个详尽的索引列表。您希望这些索引被随机排列,以便您可以随机顺序访问每个数组元素。
以下代码将以简单直接的方式执行此操作:
#!/usr/bin/python
import numpy as np
#Define a two-dimensional array
#Use any number of dimensions, and dimensions of any size
d=numpy.zeros(30).reshape((5,6))
#Get a list of indices for an array of this shape
indices=list(np.ndindex(d.shape))
#Shuffle the indices in-place
np.random.shuffle(indices)
#Access array elements using the indices to do cool stuff
for i in indices:
d[i]=5
print d
打印d
确认已访问过所有元素。
请注意,数组可以包含任意数量的维度,尺寸可以是任意大小。
这种方法的唯一缺点是,如果d
很大,那么indices
可能变得相当大。因此,拥有生成器会很不错。可悲的是,我无法想象如何建立一个改组的迭代器。
答案 2 :(得分:2)
从@ WoLpH
扩展好的答案对于2D数组,我认为这将取决于您想要或需要了解的索引。
你可以这样做:
data = np.arange(25).reshape((5,5))
x, y = np.where( a = a)
idx = zip(x,y)
np.random.shuffle(idx)
或强>
data = np.arange(25).reshape((5,5))
grid = np.indices(data.shape)
idx = zip( grid[0].ravel(), grid[1].ravel() )
np.random.shuffle(idx)
然后,您可以根据需要使用列表idx
迭代随机排序的2D数组索引,并从data
获取该索引处的值,该值保持不变。
注意:您也可以通过itertools.product
生成随机排序的索引,以防您对这套工具更加熟悉。
答案 3 :(得分:1)
使用random.sample
在0 .. A.size中生成整数,没有重复项,
然后将它们分成索引对:
import random
import numpy as np
def randint2_nodup( nsample, A ):
""" uniform int pairs, no dups:
r = randint2_nodup( nsample, A )
A[r]
for jk in zip(*r):
... A[jk]
"""
assert A.ndim == 2
sample = np.array( random.sample( xrange( A.size ), nsample )) # nodup ints
return sample // A.shape[1], sample % A.shape[1] # pairs
if __name__ == "__main__":
import sys
nsample = 8
ncol = 5
exec "\n".join( sys.argv[1:] ) # run this.py N= ...
A = np.arange( 0, 2*ncol ).reshape((2,ncol))
r = randint2_nodup( nsample, A )
print "r:", r
print "A[r]:", A[r]
for jk in zip(*r):
print jk, A[jk]
答案 4 :(得分:1)
假设您有一个大小为8x3的数据点数组
data = np.arange(50,74).reshape(8,-1)
如果你真的想要抽样,如你所说,所有指数都是2d对,我能想到的最紧凑的方法是:
#generate a permutation of data's size, coerced to data's shape
idxs = divmod(np.random.permutation(data.size),data.shape[1])
#iterate over it
for x,y in zip(*idxs):
#do something to data[x,y] here
pass
但是,一般来说,人们通常不需要将二维数组作为二维数组来访问它们,在这种情况下,一个人可以更紧凑。只需在数组上创建一个视图,并为自己保存一些索引争用。
flat_data = data.ravel()
flat_idxs = np.random.permutation(flat_data.size)
for i in flat_idxs:
#do something to flat_data[i] here
pass
这仍将根据您的需要置换2d“原始”数组。要看到这一点,请尝试:
flat_data[12] = 1000000
print data[4,0]
#returns 1000000
答案 5 :(得分:1)
使用numpy 1.7或更高版本的人也可以使用内置函数numpy.random.choice