Получить повторное представление 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
производит тот же массив, что и b
copy
- то есть те же флаги и те же __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
В простейшем случае существует только один расширенный индекс. Один расширенный индекс может, например, заменить срез, и результирующий массив будет таким же, однако это копия и может иметь другую структуру памяти. Срез предпочтительнее, когда это возможно.