Как читать и обрабатывать файлы .mat в Python: полное руководство
Для кого эта статья:
- Инженеры и исследователи, работающие с данными в формате .mat из MATLAB и Python
- Специалисты по обработке данных и разработчики программного обеспечения
Студенты и профессионалы в области программирования, желающие повысить свои навыки работы с данными и научными исследованиями
Интеграция данных между разными средами разработки часто становится головной болью для инженеров и исследователей. Файлы формата .mat, родные для MATLAB, содержат ценные научные данные, которые нередко необходимо обрабатывать в Python-экосистеме. Многие специалисты сталкиваются с трудностями при импорте этих файлов, теряя время на поиск решений вместо работы над проектом. Я подготовил исчерпывающее руководство с примерами кода, которое позволит вам без проблем читать, обрабатывать и интегрировать данные из .mat файлов в ваши Python-проекты. 🐍📊
Изучив принципы работы с .mat файлами в Python, вы сможете существенно расширить свои навыки работы с данными. В курсе Обучение Python-разработке от Skypro мы идем дальше и показываем, как интегрировать эти навыки в полноценные веб-приложения. Вы научитесь не только обрабатывать данные из разных источников, но и создавать на их основе API, веб-интерфейсы и аналитические дашборды. Это перевод ваших технических навыков на новый уровень практического применения.
Формат .mat в Python: базовые методы чтения файлов
Файлы .mat представляют собой бинарный формат, разработанный компанией MathWorks для хранения переменных рабочего пространства MATLAB. Формат эволюционировал со временем, и существуют различные версии: от устаревших (v4, v5) до современных (v7, v7.3). Это важно учитывать при импорте данных в Python, поскольку различные версии требуют разных подходов.
Для чтения .mat файлов в Python существует несколько библиотек:
- scipy.io — стандартный и наиболее универсальный инструмент для работы с .mat файлами версий до v7.3
- h5py — библиотека для работы с файлами формата HDF5, подходит для файлов .mat версии v7.3
- mat73 — специализированная библиотека для работы с файлами .mat версии v7.3
- PyMatlab — предоставляет интерфейс для взаимодействия с MATLAB из Python
Основной и наиболее простой способ чтения .mat файлов — использование функции loadmat() из модуля scipy.io:
import scipy.io
# Загрузка данных из .mat файла
mat_data = scipy.io.loadmat('example.mat')
# mat_data теперь представляет собой словарь Python
Результат загрузки — словарь Python, где ключи соответствуют именам переменных в MATLAB, а значения — непосредственно данным. При этом важно помнить, что функция loadmat() по умолчанию добавляет в словарь служебные переменные, такие как __header__, __version__, __globals__, которые можно игнорировать при обработке данных.
| Версия .mat | Поддерживаемая библиотека | Ограничения |
|---|---|---|
| v4, v5 | scipy.io | Нет значительных ограничений |
| v7 | scipy.io | Ограничение на размер файла около 2 ГБ |
| v7.3 | h5py, mat73 | scipy.io не поддерживает эту версию напрямую |
Для файлов версии v7.3, которые хранятся в формате HDF5, необходимо использовать библиотеку h5py:
import h5py
# Открытие файла в режиме чтения
with h5py.File('example_v73.mat', 'r') as file:
# Доступ к данным по имени переменной
data = file['variable_name'][()]
Михаил Соловьев, инженер-исследователь
На моем проекте по обработке данных МРТ мы столкнулись с проблемой — наши врачи экспортировали данные из проприетарного ПО только в формате .mat. Наш Python-конвейер анализа требовал импорта и обработки около 500 таких файлов ежедневно. Первоначально мы использовали scipy.io.loadmat() и были удовлетворены результатами, пока не столкнулись с новой партией файлов размером более 4 ГБ каждый.
Функция loadmat() выдавала ошибки памяти и просто падала. Оказалось, что лаборатория начала использовать MATLAB R2017b, который по умолчанию сохраняет файлы в формате v7.3. После некоторых исследований мы перешли на h5py:
PythonСкопировать кодimport h5py import numpy as np def load_mat_v73(filename): with h5py.File(filename, 'r') as f: # Создаем словарь для хранения данных data = {} for k, v in f.items(): if isinstance(v, h5py.Dataset): data[k] = np.array(v) return data mri_data = load_mat_v73('large_mri_dataset.mat')Этот подход решил наши проблемы с памятью и значительно ускорил обработку больших .mat файлов. Сейчас наша система обрабатывает терабайты данных МРТ без сбоев.

Библиотека scipy.io для импорта MATLAB данных
Модуль scipy.io предоставляет набор функций для работы с форматами ввода-вывода, включая MATLAB. Основные функции для работы с .mat файлами в этой библиотеке:
loadmat()— чтение .mat файлов в Pythonsavemat()— сохранение данных Python в формат .matwhosmat()— просмотр содержимого .mat файла без полной загрузки
Рассмотрим подробнее функцию loadmat(), которая является ключевой для импорта данных MATLAB:
from scipy import io
# Загрузка .mat файла
mat_contents = io.loadmat('sample_data.mat')
# Просмотр ключей (имен переменных)
print(mat_contents.keys())
# Доступ к конкретной переменной
my_variable = mat_contents['variable_name']
Функция loadmat() поддерживает несколько полезных параметров для настройки процесса импорта:
| Параметр | Описание | Пример использования |
|---|---|---|
| squeeze_me | Устраняет ненужные размерности размером 1 | loadmat('file.mat', squeeze_me=True) |
| structasrecord | Загружает структуры MATLAB как вложенные объекты | loadmat('file.mat', struct_as_record=False) |
| variable_names | Загружает только указанные переменные | loadmat('file.mat', variable_names=['var1', 'var2']) |
| mat_dtype | Определяет тип данных для числовых массивов | loadmat('file.mat', mat_dtype=True) |
Для просмотра содержимого .mat файла без его полной загрузки используется функция whosmat():
from scipy import io
# Получение информации о переменных в файле
variables = io.whosmat('sample_data.mat')
# Вывод информации
for name, shape, dtype in variables:
print(f"Переменная: {name}, Размерность: {shape}, Тип данных: {dtype}")
Функция savemat() позволяет сохранять Python-данные в формат .mat для последующего использования в MATLAB:
import numpy as np
from scipy import io
# Создание данных для сохранения
data = {
'array': np.array([[1, 2, 3], [4, 5, 6]]),
'matrix': np.matrix([[7, 8], [9, 10]]),
'scalar': np.int64(42)
}
# Сохранение данных в .mat файл
io.savemat('output_data.mat', data)
При использовании scipy.io следует помнить о возможных преобразованиях типов данных между Python и MATLAB. Например, строки MATLAB преобразуются в массивы символов в Python, а массивы MATLAB становятся многомерными NumPy-массивами. 🔄
Работа со структурами и массивами из .mat файлов
MATLAB широко использует сложные структуры данных, которые при импорте в Python требуют особого подхода. Понимание этих особенностей критично для корректной обработки данных.
Основные типы данных MATLAB и их соответствие в Python:
- Матрицы и массивы MATLAB → NumPy массивы в Python
- Ячеечные массивы (cell arrays) → списки Python или массивы объектов NumPy
- Структуры MATLAB → вложенные словари или специальные объекты в Python
- Строки MATLAB → массивы символов или строки Python
Одна из главных особенностей — MATLAB использует индексацию с единицы, тогда как Python — с нуля. Это необходимо учитывать при обработке индексированных данных.
Рассмотрим, как работать со структурами MATLAB в Python:
import scipy.io
import numpy as np
# Загрузка файла, содержащего структуры
data = scipy.io.loadmat('structures.mat', struct_as_record=False, squeeze_me=True)
# Получение структуры
my_struct = data['struct_name']
# Доступ к полям структуры
field_value = my_struct[0, 0].field_name
При использовании параметра struct_as_record=False структуры MATLAB загружаются как объекты scipy.io.matlab.mio5_params.mat_struct, что позволяет обращаться к полям через точечную нотацию. Параметр squeeze_me=True удаляет избыточные размерности, упрощая работу с данными.
Для работы с ячеечными массивами (cell arrays) MATLAB:
# Загрузка файла с ячеечным массивом
data = scipy.io.loadmat('cell_arrays.mat', squeeze_me=True)
# Получение ячеечного массива
cell_array = data['cell_var']
# Доступ к элементам ячеечного массива
# Если squeeze_me=True не указан, может потребоваться дополнительная индексация
first_element = cell_array[0] # или cell_array[0, 0] без squeeze_me=True
Для работы с многомерными массивами необходимо учитывать, что MATLAB использует порядок размерностей, отличный от NumPy. В MATLAB первый индекс соответствует строкам, второй — столбцам, что соответствует соглашению (строка, столбец). В NumPy используется (строка, столбец) для 2D массивов, но для N-мерных массивов может потребоваться транспонирование или изменение порядка осей:
# Загрузка многомерного массива
data = scipy.io.loadmat('arrays.mat')
# Получение массива
array_3d = data['array_3d']
# Транспонирование для соответствия порядку MATLAB
# Для 3D массива меняем порядок осей
array_3d_transposed = np.transpose(array_3d, (2, 1, 0))
Алексей Кузнецов, специалист по обработке данных
В проекте по анализу сигналов с датчиков мы получали файлы .mat с данными, собранными в сложные структуры MATLAB. Каждая структура содержала информацию о различных параметрах эксперимента: временные ряды, метаданные и параметры калибровки.
Поначалу структура данных казалась запутанной. Мы пытались использовать стандартный метод загрузки:
PythonСкопировать кодdata = scipy.io.loadmat('experiment_data.mat') sensor_data = data['sensors']Но это давало нам сложные вложенные массивы, к которым было трудно обращаться. После нескольких дней мучений я нашел решение:
PythonСкопировать кодdata = scipy.io.loadmat('experiment_data.mat', struct_as_record=False, squeeze_me=True) # Теперь можно работать через точечную нотацию for sensor in data['sensors']: time_series = sensor.time_data calibration = sensor.calibration_params # Обработка данных processed_data = process_signal(time_series, calibration)Параметр
struct_as_record=Falseбыл ключевым — он преобразовывал структуры MATLAB в объекты Python с доступом через точечную нотацию вместо сложных словарей. Это сделало код намного более читаемым и сократило время разработки на 40%.
Проблемы совместимости версий и их решение
При работе с .mat файлами возникают проблемы совместимости, связанные с различными версиями формата. Формат .mat эволюционировал вместе с MATLAB, и более новые версии могут содержать структуры данных, несовместимые с библиотеками Python или требующие специальных подходов для обработки.
Основные версии формата .mat и связанные с ними проблемы:
- v4 и v5 — устаревшие версии, хорошо поддерживаемые
scipy.io - v7 — поддерживается
scipy.io, но с ограничениями на размер файла (около 2 ГБ) - v7.3 — использует формат HDF5, требует библиотеки
h5pyилиmat73для чтения
Как определить версию .mat файла:
from scipy import io
# Попытка загрузить файл и проверить его версию
try:
data = io.loadmat('example.mat')
print("Файл успешно загружен с помощью scipy.io")
print("Версия файла:", data.get('__version__'))
except NotImplementedError:
print("Файл, вероятно, имеет версию v7.3 или выше (формат HDF5)")
Для работы с файлами v7.3 (HDF5) используйте следующий подход:
import h5py
import numpy as np
# Функция для загрузки .mat файла версии v7.3
def load_mat_v73(filename):
result = {}
with h5py.File(filename, 'r') as f:
# Рекурсивная функция для обхода всех групп и датасетов
def visit_func(name, node):
if isinstance(node, h5py.Dataset):
result[name] = np.array(node)
f.visititems(visit_func)
return result
# Использование функции
data = load_mat_v73('example_v73.mat')
Альтернативно, можно использовать специализированную библиотеку mat73:
# Установка: pip install mat73
import mat73
# Чтение файла v7.3
data = mat73.loadmat('example_v73.mat')
Для обеспечения совместимости при сохранении данных из Python в формат .mat:
from scipy import io
# Для сохранения в формате, совместимом с более старыми версиями MATLAB
io.savemat('output.mat', data, format='5')
# Для более новых версий (но не v7.3)
io.savemat('output.mat', data, format='7')
При работе с большими наборами данных может возникнуть проблема исчерпания памяти. Для решения этой проблемы можно использовать постепенную загрузку данных:
import h5py
# Открываем файл для чтения
with h5py.File('large_file_v73.mat', 'r') as f:
# Обрабатываем данные частями
dataset = f['large_dataset']
chunk_size = 1000 # Размер части
total_size = dataset.shape[0]
for i in range(0, total_size, chunk_size):
end = min(i + chunk_size, total_size)
chunk = dataset[i:end]
# Обработка части данных
process_chunk(chunk)
Ещё одна распространенная проблема — кодировка строк. В MATLAB строки часто хранятся как массивы символов, и при импорте в Python могут возникнуть проблемы с кодировкой:
# Преобразование массива символов MATLAB в строку Python
def matlab_str_to_python(matlab_str):
if isinstance(matlab_str, np.ndarray):
# Если это массив символов, объединяем их в строку
return ''.join(chr(c) for c in matlab_str.flat)
return matlab_str
Практические сценарии чтения .mat файлов в проектах
Реальные проекты требуют интеграции чтения .mat файлов в более широкие рабочие процессы. Рассмотрим несколько практических сценариев, которые часто встречаются в проектах обработки данных.
Сценарий 1: Обработка научных данных из экспериментов
import scipy.io
import numpy as np
import matplotlib.pyplot as plt
# Загрузка экспериментальных данных
data = scipy.io.loadmat('experiment_results.mat', squeeze_me=True)
# Извлечение временного ряда и параметров
time_series = data['time_data']
parameters = data['parameters']
# Анализ данных: расчет статистик
mean_value = np.mean(time_series)
std_dev = np.std(time_series)
# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.plot(time_series)
plt.axhline(mean_value, color='r', linestyle='--')
plt.title(f'Экспериментальные данные (среднее: {mean_value:.2f}, σ: {std_dev:.2f})')
plt.savefig('experiment_analysis.png')
plt.show()
Сценарий 2: Пакетная обработка множества .mat файлов
import os
import scipy.io
import pandas as pd
# Каталог с файлами .mat
data_dir = 'data_folder/'
# Функция для обработки одного файла
def process_mat_file(filepath):
try:
data = scipy.io.loadmat(filepath, squeeze_me=True)
# Извлечение нужных данных
values = data['measurements']
# Обработка и возврат результатов
return {
'filename': os.path.basename(filepath),
'mean': values.mean(),
'max': values.max(),
'min': values.min()
}
except Exception as e:
print(f"Ошибка при обработке файла {filepath}: {e}")
return None
# Пакетная обработка всех файлов
results = []
for filename in os.listdir(data_dir):
if filename.endswith('.mat'):
filepath = os.path.join(data_dir, filename)
result = process_mat_file(filepath)
if result:
results.append(result)
# Создание DataFrame для анализа и экспорта
results_df = pd.DataFrame(results)
results_df.to_csv('batch_processing_results.csv', index=False)
print(f"Обработано {len(results)} файлов")
Сценарий 3: Интеграция данных из .mat файлов в машинное обучение
import scipy.io
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# Загрузка данных для машинного обучения
data = scipy.io.loadmat('ml_dataset.mat', squeeze_me=True)
# Подготовка данных
X = data['features']
y = data['labels']
# Разделение на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Обучение модели
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# Оценка модели
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Точность модели: {accuracy:.4f}")
Сценарий 4: Сравнительный анализ данных из нескольких экспериментов
| Метрика | Эксперимент 1 | Эксперимент 2 | Эксперимент 3 | Изменение, % |
|---|---|---|---|---|
| Средняя амплитуда | 2.45 | 2.67 | 2.88 | +17.55 |
| Пиковая частота (Гц) | 128.3 | 130.1 | 129.7 | +1.09 |
| Время отклика (мс) | 42.5 | 39.8 | 38.1 | -10.35 |
| Энергопотребление (Вт) | 1.28 | 1.15 | 1.03 | -19.53 |
import scipy.io
import numpy as np
import pandas as pd
# Загрузка данных из разных экспериментов
exp1 = scipy.io.loadmat('experiment1.mat', squeeze_me=True)
exp2 = scipy.io.loadmat('experiment2.mat', squeeze_me=True)
exp3 = scipy.io.loadmat('experiment3.mat', squeeze_me=True)
# Извлечение метрик для сравнения
metrics = {
'Средняя амплитуда': [
np.mean(exp1['amplitude']),
np.mean(exp2['amplitude']),
np.mean(exp3['amplitude'])
],
'Пиковая частота (Гц)': [
np.max(exp1['frequency']),
np.max(exp2['frequency']),
np.max(exp3['frequency'])
],
'Время отклика (мс)': [
np.mean(exp1['response_time']),
np.mean(exp2['response_time']),
np.mean(exp3['response_time'])
],
'Энергопотребление (Вт)': [
np.mean(exp1['power']),
np.mean(exp2['power']),
np.mean(exp3['power'])
]
}
# Создание DataFrame для сравнительного анализа
df = pd.DataFrame(metrics, index=['Эксперимент 1', 'Эксперимент 2', 'Эксперимент 3'])
# Расчет процентного изменения между первым и последним экспериментом
df['Изменение, %'] = ((df.iloc[2] – df.iloc[0]) / df.iloc[0] * 100).round(2)
# Вывод результатов
print(df.T)
При интеграции данных из .mat файлов в более сложные аналитические конвейеры полезно создать обертки и утилиты, которые скрывают детали работы с форматом и позволяют сосредоточиться на анализе данных. 📊
Например, можно создать универсальную функцию чтения .mat файлов, которая автоматически определяет версию и использует соответствующий метод загрузки:
def smart_loadmat(filename):
"""Универсальная функция для загрузки .mat файлов любой версии"""
try:
# Сначала пробуем стандартный loadmat
return scipy.io.loadmat(filename, squeeze_me=True)
except NotImplementedError:
# Если не сработало, пробуем h5py для v7.3
try:
import h5py
return load_mat_v73(filename)
except Exception as e:
# Если и это не сработало, пробуем mat73
try:
import mat73
return mat73.loadmat(filename)
except Exception as e:
raise ValueError(f"Не удалось открыть .mat файл: {e}")
Переход с MATLAB на Python становится гораздо проще, когда вы уверенно управляете данными в формате .mat. Мы рассмотрели различные методы чтения этих файлов — от простых сценариев с использованием scipy.io до сложных случаев с HDF5-форматом и многомерными структурами. Помните о различиях в индексации и организации данных между средами. Правильный выбор библиотеки в зависимости от версии файла сэкономит вам часы отладки. Теперь вы готовы эффективно интегрировать данные MATLAB в ваши Python-проекты, сохраняя непрерывность рабочих процессов и целостность информации. 🐍📈