Каков порядок заполнения Numpy из файла для двумерного массива? - PullRequest
1 голос
/ 01 мая 2020

Я пытаюсь прочитать структурированный двоичный файл, используя функцию numpy.fromfile(). В моем случае у меня есть numpy.dtype(), который используется для определения пользовательского типа данных для использования с np.fromfile().
. Я воспроизведу соответствующую часть структуры данных здесь (поскольку полная структура довольно длинная) :

('RawData', np.int32, (2, BlockSize))  

это будет читать BlockSize*2 количество int32s в поле RawData, даст матрицу 2xBlockSize. Именно здесь у меня возникают проблемы, потому что я хочу повторить поведение функции fread () Matlab, в которой матрица c заполняется в порядке столбцов . Что касается NumPy s fromfile(), это не упоминается (по крайней мере, я не смог его найти).

Неважно, NumPy fromfile() должен работать как Matlab's fread(), но я должен знать, как NumPy fromfile() работает для соответствующего кодирования.

Теперь возникает вопрос: каков порядок заполнения двумерного массива в функции NumPy fromfile() при использовании пользовательского типа данных?

Ответы [ 2 ]

2 голосов
/ 01 мая 2020

fromfile и tofile чтение / запись плоско, 1d, массивы:

In [204]: x = np.arange(1,11).astype('int32')                                                          
In [205]: x.tofile('data615')                                                                          

fromfile возвращает массив 1d:

In [206]: np.fromfile('data615',np.int32)                                                              
Out[206]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10], dtype=int32)

x.reshape(2,5).tofile(...) сохранит тоже самое. tofile не сохраняет dtype или shape информацию.

изменяется на 2d, по умолчанию используется порядок C:

In [207]: np.fromfile('data615',np.int32).reshape(2,5)                                                 
Out[207]: 
array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10]], dtype=int32)

, но его можно изменить на MATLAB вроде:

In [208]: np.fromfile('data615',np.int32).reshape(2,5, order='F')                                      
Out[208]: 
array([[ 1,  3,  5,  7,  9],
       [ 2,  4,  6,  8, 10]], dtype=int32)

Базовый databuffer такой же, только массив байтов 1d.

edit

Файл может быть прочитан как целое число 2 структура:

In [249]: np.fromfile('data615','i4,i4')                                                               
Out[249]: 
array([(1,  2), (3,  4), (5,  6), (7,  8), (9, 10)],
      dtype=[('f0', '<i4'), ('f1', '<i4')])
In [250]: _['f0']                                                                                      
Out[250]: array([1, 3, 5, 7, 9], dtype=int32)

Это все еще одномерный массив, но с числами, сгруппированными по 2 с.

Преобразование в сложное:

In [252]: xx = np.fromfile('data615','i4,i4')                                                          
In [253]: xx['f0']+1j*xx['f1']                                                                         
Out[253]: array([1. +2.j, 3. +4.j, 5. +6.j, 7. +8.j, 9.+10.j])
In [254]: _.dtype                                                                                      
Out[254]: dtype('complex128')

Если данные были сохранены как с плавающей запятой, мы можем загрузить их как комплекс напрямую:

In [255]: x.astype(np.float32).tofile('data615f')                                                      
In [257]: xx = np.fromfile('data615f',np.complex64)                                                    
In [258]: xx                                                                                           
Out[258]: array([1. +2.j, 3. +4.j, 5. +6.j, 7. +8.j, 9.+10.j], dtype=complex64)

Другой способ получить комплекс из целочисленной последовательности:

In [261]: np.fromfile('data615', np.int32).reshape(5,2)                                                
Out[261]: 
array([[ 1,  2],
       [ 3,  4],
       [ 5,  6],
       [ 7,  8],
       [ 9, 10]], dtype=int32)
In [262]: xx = np.fromfile('data615', np.int32).reshape(5,2)                                           
In [263]: xx[:,0]+1j*xx[:,1]                                                                           
Out[263]: array([1. +2.j, 3. +4.j, 5. +6.j, 7. +8.j, 9.+10.j])
1 голос
/ 01 мая 2020

По умолчанию при создании нового двумерного массива NumPy будет использовать порядок "C", который равен row-major . Это противоположно порядку, используемому Matlab.

Например, если BlockSize равно 4, а необработанные данные равны

0 1 2 3 4 5 6 7

, то массив 2 x 4 будет

[[0, 1, 2, 3],
 [4, 5, 6, 7]]

С Matlab и теми же необработанными данными массив 2 x 4 будет

[[0, 2, 4, 6],
 [1, 3, 5, 7]]
...