【问题标题】:Indexing Numpy arrays with range() throws shape mismatch error使用 range() 索引 Numpy 数组会引发形状不匹配错误
【发布时间】:2019-06-14 19:39:51
【问题描述】:

我是 Numpy 和 OpenCV 的新手。我觉得奇怪的是 Numpy 数组只能用第一个维度的范围进行索引:

>>> import numpy
>>> 
>>> a = numpy.zeros((3, 3), dtype=numpy.int8)
>>> 
>>> i_range = range(3)
>>> j_range = range(3)
>>> 
>>> print(i_range)
range(0, 3)
>>> print(j_range)
range(0, 3)
>>> print(a[i_range, j_range])
[0 0 0]
>>> print(a[0:3, 0:3])
[[0 0 0]
 [0 0 0]
 [0 0 0]]
>>> a[i_range, j_range] = numpy.ones((3,3), dtype=numpy.int8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: shape mismatch: value array of shape (3,3) could not be broadcast to indexing result of shape (3,)
>>> a[0:3, 0:3] = numpy.ones((3,3), dtype=numpy.int8)
>>> a
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]], dtype=int8)

使用范围索引会返回一个长度为 3 的向量,使用全数索引会返回一个 3x3 数组。前者在给索引数组赋值时会报错,后者工作正常。

为什么会这样?

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    您使用range 而不是列表这一事实与您的错误无关。

    创建一个具有不同值的数组:

    In [30]: a = np.arange(9).reshape(3,3)                                          
    In [31]: a                                                                      
    Out[31]: 
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])
    

    使用两个范围进行索引会产生一个一维数组,在本例中是对角线。

    In [32]: a[range(3),range(3)]                                                   
    Out[32]: array([0, 4, 8])
    

    a[[0,1,2], [0,1,2]] 会做同样的事情。错误中的 (3,) 块指的是这个一维数组。

    要获得与[0:3, 0:3] 切片等效的块,您必须使用相互广播的数组。一个方便的实用程序是ix_

    In [33]: np.ix_(range(3), range(3))                                             
    Out[33]: 
    (array([[0],
            [1],
            [2]]), array([[0, 1, 2]]))
    

    注意一个数组是(3,1),另一个是(1,3);一起广播它们引用一个 (3,3) 值块:

    In [34]: a[np.ix_(range(3), range(3))]                                          
    Out[34]: 
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])
    

    现在我们可以为它分配一个 (3,3) 数组:

    In [35]: a[np.ix_(range(3), range(3))] = np.ones((3,3))                         
    In [36]: a                                                                      
    Out[36]: 
    array([[1, 1, 1],
           [1, 1, 1],
           [1, 1, 1]])
    

    【讨论】:

      【解决方案2】:

      不同之处在于,在 Python 3.x 中,range() 生成的是迭代器而不是列表。在 Python 2.x 之前,此功能由 xrange() 使用。然而,现在,只需调用 range() 就会产生一个迭代器。

      【讨论】:

      • 使用范围与列表不是问题。
      猜你喜欢
      • 2019-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 2021-05-11
      • 2018-02-17
      相关资源
      最近更新 更多