Skip to main content
 首页 » 编程设计

python之Numpy:使用不同的种子多次统一洗牌数组

2025年05月04日15powertoolsteam

我有多个 numpy 数组,它们的行数 (axis_0) 相同,我想一致地洗牌。一次洗牌后,我想用不同的随机种子再次洗牌。


到目前为止,我使用的解决方案来自 Better way to shuffle two numpy arrays in unison :

def shuffle_in_unison(a, b): 
    rng_state = numpy.random.get_state() 
    numpy.random.shuffle(a) 
    numpy.random.set_state(rng_state) 
    numpy.random.shuffle(b) 

但是,这不适用于多个齐奏洗牌,因为 rng_state 始终相同。


我尝试使用 RandomState 为每次调用获取不同的种子,但这甚至不适用于单个齐奏随机播放:

a = np.array([1,2,3,4,5]) 
b = np.array([10,20,30,40,50]) 
 
def shuffle_in_unison(a, b): 
    r = np.random.RandomState() # different state from /dev/urandom for each call 
    state = r.get_state() 
    np.random.shuffle(a) # array([4, 2, 1, 5, 3]) 
    np.random.set_state(state) 
    np.random.shuffle(b) # array([40, 20, 50, 10, 30]) 
    # -> doesn't work 
    return a,b 
 
for i in xrange(10): 
    a,b = shuffle_in_unison(a,b) 
    print a,b 

我做错了什么?



编辑:

对于像我这样没有大数组的每个人,只需使用 Francesco ( https://stackoverflow.com/a/47156309/3955022 ) 的解决方案:

def shuffle_in_unison(a, b): 
    n_elem = a.shape[0] 
    indeces = np.random.permutation(n_elem) 
    return a[indeces], b[indeces] 

唯一的缺点就是这不是原地操作,对于我这样的大数组(500G)有点可惜。

请您参考如下方法:

我不知道你设置状态的方式有什么问题。但是我找到了另一种解决方案:不是随机播放 n 数组,而是使用 numpy.random.choice 只将它们的索引随机播放一次然后重新排序所有数组。

a = np.array([1,2,3,4,5]) 
b = np.array([10,20,30,40,5]) 
 
def shuffle_in_unison(a, b): 
     n_elem = a.shape[0] 
     indeces = np.random.choice(n_elem, size=n_elem, replace=False) 
     return a[indeces], b[indeces] 
 
 for i in xrange(5): 
     a, b = shuffle_in_unison(a ,b) 
     print(a, b) 

我得到:

[5 2 4 3 1] [50 20 40 30 10] 
[1 3 4 2 5] [10 30 40 20 50] 
[1 2 5 4 3] [10 20 50 40 30] 
[3 2 1 4 5] [30 20 10 40 50] 
[1 2 5 3 4] [10 20 50 30 40] 

编辑

感谢@Divakar 的建议。 这是使用 numpy.random.premutation 获得相同结果的更具可读性的方法。

def shuffle_in_unison(a, b): 
     n_elem = a.shape[0] 
     indeces = np.random.permutation(n_elem) 
     return a[indeces], b[indeces]