Файловый ввод-вывод (scipy.io)#

Файлы MATLAB#

loadmat(file_name[, mdict, appendmat, spmatrix])

Загрузить файл MATLAB.

savemat(file_name, mdict[, appendmat, ...])

Сохранить словарь имён и массивов в файл .mat в стиле MATLAB.

whosmat(file_name[, appendmat])

Перечислите переменные внутри файла MATLAB.

Базовые функции#

Начнём с импорта scipy.io и вызов её sio для удобства:

>>> import scipy.io as sio

Если вы используете IPython, попробуйте автодополнение с помощью Tab sio. Среди множества опций вы найдете:

sio.loadmat
sio.savemat
sio.whosmat

Это высокоуровневые функции, которые вы, скорее всего, будете использовать при работе с файлами MATLAB. Вы также найдёте:

sio.matlab

Это пакет, из которого loadmat, savemat, и whosmat импортируются. Внутри sio.matlab, вы найдете mio модуль Этот модуль содержит механизм, который loadmat и savemat использовать. Время от времени вы можете обнаружить, что повторно используете этот механизм.

Как мне начать?#

У вас может быть .mat файл, который вы хотите прочитать в SciPy. Или вы хотите передать некоторые переменные из SciPy / NumPy в MATLAB.

Чтобы не использовать лицензию MATLAB, начнем в Octave. Octave имеет совместимые с MATLAB функции save и load. Запустите Octave (octave в командной строке для меня):

octave:1> a = 1:12
a =

   1   2   3   4   5   6   7   8   9  10  11  12

octave:2> a = reshape(a, [1 3 4])
a =

ans(:,:,1) =

   1   2   3

ans(:,:,2) =

   4   5   6

ans(:,:,3) =

   7   8   9

ans(:,:,4) =

   10   11   12

octave:3> save -6 octave_a.mat a % MATLAB 6 compatible
octave:4> ls octave_a.mat
octave_a.mat

Теперь к Python:

>>> mat_contents = sio.loadmat('octave_a.mat')
>>> mat_contents
{'__header__': b'MATLAB 5.0 MAT-file, written
 by Octave 3.2.3, 2010-05-30 02:13:40 UTC',
 '__version__': '1.0',
 '__globals__': [],
 'a': array([[[ 1.,  4.,  7., 10.],
              [ 2.,  5.,  8., 11.],
              [ 3.,  6.,  9., 12.]]])}
>>> oct_a = mat_contents['a']
>>> oct_a
array([[[  1.,   4.,   7.,  10.],
        [  2.,   5.,   8.,  11.],
        [  3.,   6.,   9.,  12.]]])
>>> oct_a.shape
(1, 3, 4)

Теперь попробуем наоборот:

>>> import numpy as np
>>> vect = np.arange(10)
>>> vect.shape
(10,)
>>> sio.savemat('np_vector.mat', {'vect':vect})

Затем обратно в Octave:

octave:8> load np_vector.mat
octave:9> vect
vect =

  0  1  2  3  4  5  6  7  8  9

octave:10> size(vect)
ans =

    1   10

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

>>> sio.whosmat('octave_a.mat')
[('a', (1, 3, 4), 'double')]

whosmat возвращает список кортежей, по одному для каждого массива (или другого объекта) в файле. Каждый кортеж содержит имя, форму и тип данных массива.

Структуры MATLAB#

Структуры MATLAB немного похожи на словари Python, за исключением того, что имена полей должны быть строками. Любой объект MATLAB может быть значением поля. Как и для всех объектов в MATLAB, структуры фактически являются массивами структур, где отдельная структура — это массив формы (1, 1).

octave:11> my_struct = struct('field1', 1, 'field2', 2)
my_struct =
{
  field1 =  1
  field2 =  2
}

octave:12> save -6 octave_struct.mat my_struct

Мы можем загрузить это в Python:

>>> mat_contents = sio.loadmat('octave_struct.mat')
>>> mat_contents
 {'__header__': b'MATLAB 5.0 MAT-file, written by Octave 3.2.3, 2010-05-30 02:00:26 UTC',
  '__version__': '1.0',
  '__globals__': [],
  'my_struct': array([[(array([[1.]]), array([[2.]]))]], dtype=[('field1', 'O'), ('field2', 'O')])
 }
>>> oct_struct = mat_contents['my_struct']
>>> oct_struct.shape
(1, 1)
>>> val = oct_struct[0, 0]
>>> val
np.void((array([[1.]]), array([[2.]])), dtype=[('field1', 'O'), ('field2', 'O')])
>>> val['field1']
array([[ 1.]])
>>> val['field2']
array([[ 2.]])
>>> val.dtype
dtype([('field1', 'O'), ('field2', 'O')])

В версиях SciPy начиная с 0.12.0, структуры MATLAB возвращаются как структурированные массивы NumPy, с полями, названными по полям структуры. Вы можете увидеть имена полей в dtype вывод выше. Также обратите внимание:

>>> val = oct_struct[0, 0]

и:

octave:13> size(my_struct)
ans =

   1   1

Таким образом, в MATLAB массив структур должен быть как минимум двумерным, и мы воспроизводим это при чтении в SciPy. Если вы хотите удалить все размерности длины 1, попробуйте это:

>>> mat_contents = sio.loadmat('octave_struct.mat', squeeze_me=True)
>>> oct_struct = mat_contents['my_struct']
>>> oct_struct.shape
()

Иногда удобнее загружать структуры MATLAB как объекты Python, а не структурированные массивы NumPy - это может сделать синтаксис доступа в Python более похожим на синтаксис в MATLAB. Для этого используйте struct_as_record=False установка параметра на loadmat.

>>> mat_contents = sio.loadmat('octave_struct.mat', struct_as_record=False)
>>> oct_struct = mat_contents['my_struct']
>>> oct_struct[0,0].field1
array([[ 1.]])

struct_as_record=False хорошо работает с squeeze_me:

>>> mat_contents = sio.loadmat('octave_struct.mat', struct_as_record=False, squeeze_me=True)
>>> oct_struct = mat_contents['my_struct']
>>> oct_struct.shape # but no - it's a scalar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'mat_struct' object has no attribute 'shape'
>>> type(oct_struct)

>>> oct_struct.field1
1.0

Сохранение структурных массивов может быть выполнено различными способами. Один простой метод — использовать словари:

>>> a_dict = {'field1': 0.5, 'field2': 'a string'}
>>> sio.savemat('saved_struct.mat', {'a_dict': a_dict})

загружается как:

octave:21> load saved_struct
octave:22> a_dict
a_dict =

  scalar structure containing the fields:

    field2 = a string
    field1 =  0.50000

Вы также можете сохранить структуры обратно в MATLAB (или Octave в нашем случае) вот так:

>>> dt = [('f1', 'f8'), ('f2', 'S10')]
>>> arr = np.zeros((2,), dtype=dt)
>>> arr
array([(0.0, ''), (0.0, '')],
      dtype=[('f1', '
>>> arr[0]['f1'] = 0.5
>>> arr[0]['f2'] = 'python'
>>> arr[1]['f1'] = 99
>>> arr[1]['f2'] = 'not perl'
>>> sio.savemat('np_struct_arr.mat', {'arr': arr})

Массивы ячеек MATLAB#

Ячейковые массивы в MATLAB довольно похожи на списки Python в том смысле, что элементы в массивах могут содержать любой тип объекта MATLAB. На самом деле, они наиболее похожи на объектные массивы NumPy, и именно так мы загружаем их в NumPy.

octave:14> my_cells = {1, [2, 3]}
my_cells =
{
  [1,1] =  1
  [1,2] =

     2   3

}

octave:15> save -6 octave_cells.mat my_cells

Вернуться к Python:

>>> mat_contents = sio.loadmat('octave_cells.mat')
>>> oct_cells = mat_contents['my_cells']
>>> print(oct_cells.dtype)
object
>>> val = oct_cells[0,0]
>>> val
array([[ 1.]])
>>> print(val.dtype)
float64

Сохранение в массив ячеек MATLAB просто включает создание объектного массива NumPy:

>>> obj_arr = np.zeros((2,), dtype=object)
>>> obj_arr[0] = 1
>>> obj_arr[1] = 'a string'
>>> obj_arr
array([1, 'a string'], dtype=object)
>>> sio.savemat('np_cells.mat', {'obj_arr': obj_arr})
octave:16> load np_cells.mat
octave:17> obj_arr
obj_arr =
{
  [1,1] = 1
  [2,1] = a string
}

IDL файлы#

readsav(file_name[, idict, python_dict, ...])

Чтение файла IDL .sav.

Файлы Matrix Market#

mminfo(источник)

Возвращает параметры размера и хранения из файлоподобного источника Matrix Market.

mmread(source, *[, spmatrix])

Считывает содержимое файла Matrix Market из источника в матрицу.

mmwrite(target, a[, comment, field, ...])

Записывает разреженный или плотный массив a в файл формата Matrix Market цель.

Звуковые файлы Wav (scipy.io.wavfile)#

read(filename[, mmap])

Открыть WAV файл.

write(имя_файла, частота, данные)

Запись массива NumPy как WAV-файла.

Файлы Arff (scipy.io.arff)#

loadarff(f)

Прочитать файл arff.

Netcdf#

netcdf_file(filename[, mode, mmap, version, ...])

Файловый объект для данных NetCDF.

Позволяет чтение файлов NetCDF (версии pupynere пакет)