これは簡単なはずなのに、何度も検索してみても答えがわかりません。基本的に、交換せずにランダムな順序でサンプリングしたいアイテムが非常にたくさんあります。この場合、それらは2D配列のセルです。小さい配列に使用するソリューションは、メモリ内の配列をシャッフルする必要があるため、変換されません。サンプリングする必要のある数が少なければ、ランダムにアイテムをサンプリングして、試した値のリストを保持することもできます。残念ながら、私は多くの場合、すべてのセルの非常に大きな割合をサンプリングする必要があります。
私が作成したいのは、次のランダムセル(xおよびyインデックス)を生成するitertools、numpy、および/またはrandomの組み合わせを使用するイテレーターです。別の可能な解決策は、0と(x_count * y_count)の間の次の乱数(置換なし)を生成するイテレーターを作成することです。これは、セルの場所にマップして戻すことができます。どちらも簡単には達成できないようです。
どんな推測にも感謝します!
これが私の現在の解決策です。
import numpy as np
import itertools as itr
import random as rdm
#works great
x_count = 10
y_count = 5
#good luck!
#x_count = 10000
#y_count = 20000
x_indices = np.arange(x_count)
y_indices = np.arange(y_count)
cell_indices = itr.product(x_indices, y_indices)
list_cell_indices = list(cell_indices)
rdm.shuffle(list_cell_indices)
for i in range(25):
print list_cell_indices[i]
したがって、現在の応答と、私が何も知らないperlを翻訳しようとしたことに基づいて、私ができる最善のことは次のことであると理解しています。
import numpy as np
import itertools as itr
import random as rdm
x_count = 10000
y_count = 5000
sample_count = 10000
keep_probability = 0.01
tried_cells = set()
kept_cells = set()
while len(kept_cells) < sample_count:
x = rdm.randint(0, x_count)
y = rdm.randint(0, y_count)
if (x, y) in tried_cells:
pass
else:
tried_cells.add((x, y))
keep = rdm.random() < keep_probability
if keep:
kept_cells.add((x,y))
print "worked"
ほとんどの場合、使用される処理時間とメモリはそれほど悪くありません。たぶん、平均セルkeep_probabilityとsample_countをチェックして、難しいケースではエラーをスローすることができます。