Получить повторное представление ndarray (которое также может быть представлением)

Я пытаюсь получить вид 2D ndarray в виде записи или структурированного массива без копирования. Кажется, это работает нормально, если a владеет данными

>>> a = np.array([[  1, 391,  14,  26],
              [ 17, 371,  15,  30],
              [641, 340,   4,   7]])
>>> b = a.view(zip('abcd',[a.dtype]*4))
array([[(1, 391, 14, 26)],
       [(17, 371, 15, 30)],
       [(641, 340, 4, 7)]], 
      dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<i8'), ('d', '<i8')])
>>> b.base is a
True

Но если a это уже вид, это не удается. Вот пример

>>> b = a[:,[0,2,1,3]]
>>> b.base is None
False
>>> b.view(zip('abcd',[a.dtype]*4))
ValueError: new type not compatible with array.

Интересно, что в этом случае b.base это транспонирование зрения

>>> (b.base == b.T).all()
True

Так что имеет смысл, что NumPy не может создать представление о том, что я хотел.

Однако, если я использую

>>> b = np.take(a,[0,2,1,3],axis=1)

Это приводит к b быть точной копией данных, чтобы работать с представлением повторного массива. Дополнительный вопрос: может ли кто-нибудь объяснить это поведение в отличие от причудливой индексации?

У меня вопрос, я иду по этому пути неправильно? Не поддерживает ли представление о том, как я это делаю? Если это так, что будет правильным способом сделать это?

1 ответ

(большое редактирование)

b является F_CONTINGUOUS (увидеть b.flags). Количество полей в представлении должно соответствовать количеству строк b, а не количество столбцов:

In [204]: b=a[:,[0,2,1,3]].view('i4,i4,i4')
In [205]: b
Out[205]: 
array([[(0, 4, 8), (2, 6, 10), (1, 5, 9), (3, 7, 11)]], 
      dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])

Более простой случай a.copy(order='F').view('i4,i4,i4')

np.take(a,[0,2,1,3],axis=1) а также a[:,[0,2,1,3]].copy() производить C_CONTIGUOUS копии, и, следовательно, могут быть просмотрены с 4 полями.

Обратите внимание также на b.base имеет 3 столбца.


(раньше спотыкаясь вокруг вопроса)

Быть представлением не проблема.

 a = np.arange(12).reshape(3,4)
 a.view('i4,i4,i4,i4')

делает просто отлично.

Делая копию первого b также работает:

 b=a[:,[0,2,1,3]].copy()
 b.view('i4,i4,i4,i4')

1-й b (без копии) есть F_CONTIGUOUS (посмотри на b.flags). Это то, что ваш b.base == b.T показывает.

np.take производит тот же массив, что и bcopy - то есть те же флаги и те же __array_interface__ дисплей.

Другие вещи, которые работают:

a[[0,2,1],:].view('i4,i4,i4,i4')
a.T[[0,2,1,3],:].T.view('i4,i4,i4,i4')

Если я заменю смешанную нарезку и индексацию массива чистой индексацией массива:

a[[[0],[1],[2]],[0,2,1,3]].view('i4,i4,i4,i4')

результат C_CONTIGUOUS, Так что есть детали в [:, [...]] что я не объяснил - в частности, почему он производит F_CONTIGUOUS копия.

Раздел документации по смешанной базовой / расширенной индексации предупреждает, что структура памяти может измениться:

http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html

В простейшем случае существует только один расширенный индекс. Один расширенный индекс может, например, заменить срез, и результирующий массив будет таким же, однако это копия и может иметь другую структуру памяти. Срез предпочтительнее, когда это возможно.

Другие вопросы по тегам