也许使用列表推导而不是循环可以解决这个问题:
import numpy as np
shape = (10,10)
N = 4
distributions = np.random.rand(*shape)
distributions = distributions/(np.sum(distributions,axis=1)[:,None])
values = np.arange(shape[0]*shape[1]).reshape(shape)
sample = np.array([np.random.choice(v,N,p=r) for v,r in zip(values,distributions)])
输出:
print(np.round(distributions,2))
[[0.03 0.22 0.1 0.09 0.2 0.1 0.11 0.05 0.08 0.01]
[0.04 0.12 0.13 0.03 0.16 0.22 0.16 0.05 0. 0.09]
[0.15 0.04 0.08 0.07 0.17 0.13 0.01 0.15 0.1 0.1 ]
[0.06 0.13 0.16 0.03 0.17 0.09 0.08 0.11 0.05 0.12]
[0.07 0.08 0.09 0.08 0.13 0.18 0.12 0.13 0.07 0.07]
[0.1 0.04 0.11 0.06 0.04 0.16 0.18 0.15 0.01 0.15]
[0.06 0.09 0.17 0.08 0.14 0.15 0.09 0.01 0.06 0.15]
[0.03 0.1 0.11 0.07 0.14 0.14 0.15 0.1 0.04 0.11]
[0.05 0.1 0.18 0.1 0.03 0.18 0.12 0.05 0.05 0.13]
[0.13 0.1 0.08 0.11 0.06 0.14 0.11 0. 0.14 0.14]]
print(sample)
[[ 6 4 8 5]
[16 19 15 10]
[25 20 24 23]
[37 34 30 31]
[41 44 46 45]
[59 55 53 57]
[64 63 65 61]
[79 75 76 77]
[85 81 83 88]
[99 96 93 90]]
如果您希望在每一行上都使用非重复样本,您可以尝试另一种优化。通过展平值和分布,您可以根据每行的各自分布创建整个矩阵的索引的非重复洗牌。使用扁平分布,属于同一行的每组值将具有(作为一组)等效分布。这意味着,如果您在它们的原始行上重新组合混洗索引但保持其稳定的混洗有序,那么您可以取一片混洗矩阵来获取您的样本:
flatDist = distributions.reshape((distributions.size,))
flatDist = flatDist/np.sum(flatDist)
randomIdx = np.random.choice(np.arange(values.size),flatDist.size,replace=False,p=flatDist)
shuffleIdx = np.array([randomIdx//shape[1],randomIdx%shape[1]])
shuffleIdx = shuffleIdx[:,np.argsort(shuffleIdx[0,:],kind="stable")]
sample = values[tuple(shuffleIdx)].reshape(shape)[:,:N]
输出:
print(sample)
[[ 3 7 2 5]
[13 12 14 16]
[27 23 25 29]
[37 31 33 36]
[47 45 48 49]
[59 50 52 54]
[62 61 60 66]
[72 78 70 77]
[87 82 83 86]
[92 98 95 93]]