Numpyアレイからランダムにセルを選択します - 交換せずに
質問
Numpyアレイからランダムにセルを選択し、それらにいくつかの処理を行う必要があるNumpyでいくつかのモデリングルーチンを書いています。すべてのセルは置換せずに選択する必要があります(同様に、セルが選択されたら再度選択できませんが、すべてのセルは最後まで選択する必要があります)。
私はこれを行う良い方法を見つけることができるIDLから移行していますが、Numpyにもこれを行う良い方法があると思います。何を提案しますか?
アップデート: 私は2Dアレイでこれをやろうとしているので、2Dインデックスのセットを取得しようとしていることを述べるべきでした。
解決
使用するのはどうですか 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]]
他のヒント
これらの答えはすべて、私には少し複雑になっているように見えました。
インデックスの徹底的なリストを生成する多次元配列があると思います。これらのインデックスをシャッフルして、ランダムに順序で各配列要素にアクセスできるようにします。
次のコードは、これを簡単かつ簡単な方法で行います。
#!/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
すべての要素がアクセスされていることを確認しました。
配列には任意の数の寸法があり、寸法は任意のサイズにできることに注意してください。
このアプローチの唯一の欠点は、ifです d
その時、大きいです indices
かなり大きくなるかもしれません。したがって、持っているといいでしょう 発生器. 。悲しいことに、私はシャッフルされたイテレーターを手作業で構築する方法を考えることができません。
@から素敵な答えを拡張するウォルフ
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
また、このツールのセットに慣れている場合にも。
使用する random.sample
0でINTを生成するには.. a.a.size of duplicatesなしで、それらをインデックスペアに分割します。
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]
サイズ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
ただし、MOEは一般的に、多くの場合、2Dアレイとして2Dアレイとしてアクセスする必要がなく、単にシャッフルするだけで、その場合はさらにコンパクトになります。アレイに1Dビューを作成し、インデックスラングリングを保存してください。
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
numpyバージョン1.7以降を使用している人は、ビルトイン関数を使用することもできます numpy.random.choice