numpy изменение метаданных массива - PullRequest
1 голос
/ 27 февраля 2020

Я знаю, что numpy хранит числа в непрерывной памяти. Так можно ли взять

a = np.array([127,127,127,127,127,127,127,127], dtype=np.uint8)

, двоичное представление 'a' - это все единицы

к этому:

b = np.array([72057594037927935], dtype=np.uint64)

, а также обратно из b -> a.

Бинарное представление - это все единицы, однако количество элементов объединяется в один 64-битный int, представление должно быть одинаковым в Numpy, только метаданные должны измениться.

Это звучит как работа для уловок шага, но мое лучшее предположение:

np.lib.stride_tricks.as_strided(a, shape=(1,), strides=(8,8))

и

np.lib.stride_tricks.as_strided(b, shape=(8,), strides=(1,8))

только для получения ValueError: несоответствие длины шагов и формы

Это нужно только для чтения, поэтому у меня нет иллюзий, что мне нужно изменить данные.

1 Ответ

2 голосов
/ 27 февраля 2020

Если вы хотите переинтерпретировать существующие данные в массиве, который вам нужен numpy.ndarray.view. В этом основное различие между .astype и .view (то есть первый преобразуется в новый тип с сохранением значений , в то время как последний сохраняет ту же память и изменяет ее интерпретацию):

import numpy as np 

a = np.array([127,127,127,127,127,127,127,127], dtype=np.uint8)
b = a.view(np.uint64) 
print(a) 
print(b) 
print(b.view(np.uint8))                                        

Это выводит

[127 127 127 127 127 127 127 127]
[9187201950435737471]
[127 127 127 127 127 127 127 127]

Обратите внимание, что 127 имеет начальный ноль в своем двоичном шаблоне, так что это не все, поэтому значение, которое мы получаем в b отличается от того, что вы ожидаете:

>>> bin(b[0])
'0b111111101111111011111110111111101111111011111110111111101111111'

>>> bin(72057594037927935)
'0b11111111111111111111111111111111111111111111111111111111'

То, что вы предполагаете, представляет собой набор uint7 значений одного бита ...

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

>>> b.base is a
True

Вывод, конечно, заключается в том, что изменение b повлияет на a:

>>> b += 3

>>> a
array([130, 127, 127, 127, 127, 127, 127, 127], dtype=uint8)

Для управления порядком байтов вы должны использовать строковые спецификации dtype , то есть a.view('<u8') (младший порядок байтов) или a.view('>u8') (старший порядковый номер). Мы можем использовать это, чтобы воспроизвести ошибочный номер в вашем вопросе:

>>> a2 = np.array([0] + [255] * 7, dtype=np.uint8)
... a2.view('>u8')
array([72057594037927935], dtype=uint64)
...