Python 为什么random.shuffle在numpy列表上失败?

Python 为什么random.shuffle在numpy列表上失败?,python,numpy,random,shuffle,Python,Numpy,Random,Shuffle,我有一个行向量数组,在其上运行random.shuffle: #!/usr/bin/env python

我有一个行向量数组,在其上运行
random.shuffle

#!/usr/bin/env python                                                                                                                                                                                                                                                

import random
import numpy as np

zzz = np.array([[0.1, 0.2, 0.3, 0.4, 0.5],
                [0.6, 0.7, 0.8, 0.9, 1. ]])

iterations = 100000
f = 0
for _ in range(iterations):
    random.shuffle(zzz)
    if np.array_equal(zzz[0], zzz[1]):
        print(zzz)
        f += 1

print(float(f)/float(iterations))
在99.6%到100%的时间内,使用
random.shuffle
on
zzz
返回一个包含相同元素的列表,例如:

使用
numpy.random.shuffle
似乎可以通过此测试并正确地洗牌行向量。我很想知道为什么随机。洗牌失败。

像这样尝试:

#!/usr/bin/env python                                                                                                                                                                                                                                                

import random
import numpy as np

zzz = np.array([[0.1, 0.2, 0.3, 0.4, 0.5],
                [0.6, 0.7, 0.8, 0.9, 1. ]])

iterations = 100000
f = 0
for _ in range(iterations):
    random.shuffle(zzz[0])
    random.shuffle(zzz[1])
    if np.array_equal(zzz[0], zzz[1]):
        print(zzz)
        f += 1

print(float(f)/float(iterations))
试着这样做:

#!/usr/bin/env python                                                                                                                                                                                                                                                

import random
import numpy as np

zzz = np.array([[0.1, 0.2, 0.3, 0.4, 0.5],
                [0.6, 0.7, 0.8, 0.9, 1. ]])

iterations = 100000
f = 0
for _ in range(iterations):
    random.shuffle(zzz[0])
    random.shuffle(zzz[1])
    if np.array_equal(zzz[0], zzz[1]):
        print(zzz)
        f += 1

print(float(f)/float(iterations))
如果查看random.shuffle的函数,它将按以下方式执行交换:

x[i], x[j] = x[j], x[i]
对于numpy.array,它将失败,而不会引发任何错误。例如:

>>> zzz[1], zzz[0] = zzz[0], zzz[1]
>>> zzz
array([[0.1, 0.2, 0.3, 0.4, 0.5],
       [0.1, 0.2, 0.3, 0.4, 0.5]])
原因是Python首先对右侧进行完全求值,然后进行赋值(这就是为什么Python可以进行单行交换),但对于numpy数组,这是不正确的

努比

蟒蛇

如果查看random.shuffle的函数,它将按以下方式执行交换:

x[i], x[j] = x[j], x[i]
对于numpy.array,它将失败,而不会引发任何错误。例如:

>>> zzz[1], zzz[0] = zzz[0], zzz[1]
>>> zzz
array([[0.1, 0.2, 0.3, 0.4, 0.5],
       [0.1, 0.2, 0.3, 0.4, 0.5]])
原因是Python首先对右侧进行完全求值,然后进行赋值(这就是为什么Python可以进行单行交换),但对于numpy数组,这是不正确的

努比

蟒蛇

random.random
可能使用就地分配,如:

In [203]: zzz[0],zzz[1]=zzz[1],zzz[0]                                                          
In [204]: zzz                                                                                  
Out[204]: 
array([[0.6, 0.7, 0.8, 0.9, 1. ],
       [0.6, 0.7, 0.8, 0.9, 1. ]])
请注意复制

但适用于列表列表:

In [205]: zl[0],zl[1]=zl[1],zl[0]                                                              
In [206]: zl                                                                                   
Out[206]: [[0.6, 0.7, 0.8, 0.9, 1.0], [0.1, 0.2, 0.3, 0.4, 0.5]]
In [207]: zl[0],zl[1]=zl[1],zl[0]                                                              
In [208]: zl                                                                                   
Out[208]: [[0.1, 0.2, 0.3, 0.4, 0.5], [0.6, 0.7, 0.8, 0.9, 1.0]]
我测试了
zl=list(zzz)
,仍然得到了数组的行为。此
zl
是一个包含
zzz
视图的列表
tolist
创建一个列表,该列表完全独立于zzz`

简而言之,
random.random
无法正确处理
ndarray
的就地修改
np.random.shuffle
设计用于处理数组的第一个dim,因此它能够正确地处理数组

ndarray
的正确分配为:

In [211]: zzz = np.array([[0.1, 0.2, 0.3, 0.4, 0.5], 
     ...:                 [0.6, 0.7, 0.8, 0.9, 1. ]]) 
     ...:                                                                                      
In [212]: zzz[[0,1]] = zzz[[1,0]]                                                              
In [213]: zzz                                                                                  
Out[213]: 
array([[0.6, 0.7, 0.8, 0.9, 1. ],
       [0.1, 0.2, 0.3, 0.4, 0.5]])
In [214]: zzz[[0,1]] = zzz[[1,0]]                                                              
In [215]: zzz                                                                                  
Out[215]: 
array([[0.1, 0.2, 0.3, 0.4, 0.5],
       [0.6, 0.7, 0.8, 0.9, 1. ]])
random.random
可能使用就地分配,如:

In [203]: zzz[0],zzz[1]=zzz[1],zzz[0]                                                          
In [204]: zzz                                                                                  
Out[204]: 
array([[0.6, 0.7, 0.8, 0.9, 1. ],
       [0.6, 0.7, 0.8, 0.9, 1. ]])
请注意复制

但适用于列表列表:

In [205]: zl[0],zl[1]=zl[1],zl[0]                                                              
In [206]: zl                                                                                   
Out[206]: [[0.6, 0.7, 0.8, 0.9, 1.0], [0.1, 0.2, 0.3, 0.4, 0.5]]
In [207]: zl[0],zl[1]=zl[1],zl[0]                                                              
In [208]: zl                                                                                   
Out[208]: [[0.1, 0.2, 0.3, 0.4, 0.5], [0.6, 0.7, 0.8, 0.9, 1.0]]
我测试了
zl=list(zzz)
,仍然得到了数组的行为。此
zl
是一个包含
zzz
视图的列表
tolist
创建一个列表,该列表完全独立于zzz`

简而言之,
random.random
无法正确处理
ndarray
的就地修改
np.random.shuffle
设计用于处理数组的第一个dim,因此它能够正确地处理数组

ndarray
的正确分配为:

In [211]: zzz = np.array([[0.1, 0.2, 0.3, 0.4, 0.5], 
     ...:                 [0.6, 0.7, 0.8, 0.9, 1. ]]) 
     ...:                                                                                      
In [212]: zzz[[0,1]] = zzz[[1,0]]                                                              
In [213]: zzz                                                                                  
Out[213]: 
array([[0.6, 0.7, 0.8, 0.9, 1. ],
       [0.1, 0.2, 0.3, 0.4, 0.5]])
In [214]: zzz[[0,1]] = zzz[[1,0]]                                                              
In [215]: zzz                                                                                  
Out[215]: 
array([[0.1, 0.2, 0.3, 0.4, 0.5],
       [0.6, 0.7, 0.8, 0.9, 1. ]])

您应该给
random.shuffle
一个列表,例如
zl=list(zzz)
zl=zzz.tolist()
。不要指望为列表设计的Python函数能够正确处理2d数组,尤其是在处理就地更改时。random.shuffle返回none,而不是修改后的列表。请参阅:@rpm10这是对OP的响应吗?您应该给出
random.shuffle
列表,例如
zl=list(zzz)
zl=zzz.tolist()
。不要指望为列表设计的Python函数能够正确处理2d数组,尤其是在处理就地更改时。random.shuffle返回none,而不是修改后的列表。请参阅:@rpm10这是对OP的响应吗?谢谢,我没有尝试在行向量中洗牌元素,但很好奇为什么numpy和本机Python库之间的行为不同。谢谢,我没有尝试在行向量中洗牌元素,但是我很好奇为什么numpy和本机Python库之间的行为是不同的。这正是我希望看到的答案,这让bug变得很清楚。谢谢这正是我希望看到的答案,这让bug变得清晰了。谢谢