文件 I/O (scipy.io
)#
另请参阅
MATLAB 文件#
|
加载 MATLAB 文件。 |
|
将名称和数组的字典保存到 MATLAB 风格的 .mat 文件中。 |
|
列出 MATLAB 文件中的变量。 |
基本函数#
首先导入 scipy.io
并将其称为 sio
以方便起见
>>> import scipy.io as sio
如果使用的是 IPython,请尝试对 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 兼容的保存和加载函数。启动 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
([[1.0]], [[2.0]])
>>> val['field1']
array([[ 1.]])
>>> val['field2']
array([[ 2.]])
>>> val.dtype
dtype([('field1', 'O'), ('field2', 'O')])
在 0.12.0 版及之后的 SciPy 版本中,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 "<stdin>", line 1, in <module>
AttributeError: 'mat_struct' object has no attribute 'shape'
>>> type(oct_struct)
<class 'scipy.io.matlab._mio5_params.mat_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', '<f8'), ('f2', 'S10')])
>>> 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 文件#
|
读取 IDL .sav 文件。 |
Matrix Market 文件#
Wav 音频文件 (scipy.io.wavfile
)#
Arff 文件 (scipy.io.arff
)#
|
读取 arff 文件。 |
Netcdf#
|
用于 NetCDF 数据的文件对象。 |
允许读取 NetCDF 文件(pupynere 包的版本)