我觉得这个应该很容易,但经过无数次搜索和尝试后,我无法找到答案.基本上我有很多项目,我想以随机顺序采样而无需替换.在这种情况下,它们是2D阵列中的单元格.我将用于较小数组的解决方案不会转换,因为它需要改组内存数组.如果我必须采样的数量很小,我也可以随机抽样物品并保留我尝试过的值列表.不幸的是,我经常需要对所有细胞中的很大一部分进行采样,尽可能多.
我想创建的是迭代器,它使用itertools,numpy和/或random的一些组合产生下一个随机单元格(x和y索引).另一种可能的解决方案是创建一个迭代器,它将产生0和(x_count * y_count)之间的下一个随机数(无替换),我可以将其映射回单元格位置.这两者似乎都不容易实现.
感谢任何sugestions!
这是我目前的解决方案.
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并为困难案例抛出错误.
解决方法:
这种方法怎么样?我首先创建x * y数组并将其重塑为2-D.然后,知道每个单元格可以由单个整数唯一标识,从0到(x * y)获取样本.
import numpy
x_count = 10000
y_count = 20000
x_indices = numpy.arange(x_count)
y_indices = numpy.arange(y_count)
large_table = numpy.arange(y_count * x_count).reshape(y_count, x_count)
print large_table
def get_random_item(sample_size):
from random import sample
for i in sample(xrange(y_count * x_count), sample_size):
y,x = divmod(i, y_count)
yield (x,y)
for x,y in get_random_item(10):
print '%12i x: %5i y: %5i' % (large_table[x][y], x,y)
哪个回报:
(首先模拟您通过产品创建的现有二维阵列)
[[ 0 1 2 ..., 9997 9998 9999]
[ 10000 10001 10002 ..., 19997 19998 19999]
[ 20000 20001 20002 ..., 29997 29998 29999]
...,
[199970000 199970001 199970002 ..., 199979997 199979998 199979999]
[199980000 199980001 199980002 ..., 199989997 199989998 199989999]
[199990000 199990001 199990002 ..., 199999997 199999998 199999999]]
然后,它返回2-dim坐标,只需通过array [x] [y]即可将其转换为单元格内容
154080675 x: 15408 y: 675
186978188 x: 18697 y: 8188
157506087 x: 15750 y: 6087
168859259 x: 16885 y: 9259
29775768 x: 2977 y: 5768
94167866 x: 9416 y: 7866
15978144 x: 1597 y: 8144
91964007 x: 9196 y: 4007
163462830 x: 16346 y: 2830
62613129 x: 6261 y: 3129
sample()声明它”用于无需替换的随机抽样’,这种方法遵循建议’这对于从大群体中抽样特别快且节省空间:样本(xrange(10000000),60).在python random页面上找到.
我注意到虽然我使用get_random_item()作为生成器,但底层sample()仍然生成一个完整列表,因此内存使用仍然是y * x sample_size,但它运行得相当迅速.