Индексирование массивов Numpy с помощью range () приводит к ошибке несоответствия формы - PullRequest
0 голосов
/ 14 июня 2019

Я новичок в 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.Первый выдает ошибку при назначении значений индексированным массивам, последний работает нормально.

Почему это происходит?

Ответы [ 2 ]

1 голос
/ 15 июня 2019

Тот факт, что вы используете 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]])

Индексирование с двумя диапазонами дает массив 1d, в данном случае диагональ.

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

a[[0,1,2], [0,1,2]] сделал бы то же самое. Блок (3,) в вашей ошибке ссылается на этот 1d массив.

Чтобы получить блок, эквивалентный срезу [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]])
0 голосов
/ 14 июня 2019

Разница в том, что в Python 3.x range () создает итератор, а не список.До Python 2.x эта функциональность использовалась xrange ().Однако теперь простой вызов range () создает итератор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...