我正在寻找一种将 NumPy 数组传递给 Matlab 的方法。
我已经设法通过使用将数组存储到图像中scipy.misc.imsave
然后使用加载它来做到这一点imread
,但这当然会导致矩阵包含0到256之间的值而不是“真实”值。
取这个矩阵除以 256 的乘积,原始 NumPy 数组中的最大值给了我正确的矩阵,但我觉得这有点乏味。
有没有更简单的方法?
当然,只需使用scipy.io.savemat
举个例子:
import numpy as np
import scipy.io
x = np.linspace(0, 2 * np.pi, 100)
y = np.cos(x)
scipy.io.savemat('test.mat', dict(x=x, y=y))
同样,还有scipy.io.loadmat
.
然后,您将其加载到 matlab 中load test
。
或者,正如@JAB 所建议的那样,您可以将内容保存到 ascii 制表符分隔的文件中(例如numpy.savetxt
)。但是,如果你走这条路,你将被限制在二维。另一方面,ascii 是通用交换格式。几乎任何东西都会处理一个分隔的文本文件。
一个简单的解决方案,无需通过文件或外部库传递数据。
Numpy 有一种将 ndarrays 转换为列表的方法,并且 matlab 数据类型可以从列表中定义。因此,何时可以转换为:
np_a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
mat_a = matlab.double(np_a.tolist())
从 matlab 到 python 需要更多的关注。没有将类型直接转换为列表的内置函数。但是我们可以访问原始数据,这些数据不是定型的,而是简单的。因此,我们使用reshape
(正确格式化)和transpose
(因为 MATLAB 和 numpy 存储数据的方式不同)。强调这一点非常重要:在您的项目中进行测试,主要是在您使用超过 2 维的矩阵时。它适用于 MATLAB 2015a 和 2 dims。
np_a = np.array(mat_a._data.tolist())
np_a = np_a.reshape(mat_a.size).transpose()
这是一个避免在 python 中迭代或使用文件 IO 的解决方案 - 以依赖(丑陋的)matlab 内部为代价:
import matlab
# This is actually `matlab._internal`, but matlab/__init__.py
# mangles the path making it appear as `_internal`.
# Importing it under a different name would be a bad idea.
from _internal.mlarray_utils import _get_strides, _get_mlsize
def _wrapper__init__(self, arr):
assert arr.dtype == type(self)._numpy_type
self._python_type = type(arr.dtype.type().item())
self._is_complex = np.issubdtype(arr.dtype, np.complexfloating)
self._size = _get_mlsize(arr.shape)
self._strides = _get_strides(self._size)[:-1]
self._start = 0
if self._is_complex:
self._real = arr.real.ravel(order='F')
self._imag = arr.imag.ravel(order='F')
else:
self._data = arr.ravel(order='F')
_wrappers = {}
def _define_wrapper(matlab_type, numpy_type):
t = type(matlab_type.__name__, (matlab_type,), dict(
__init__=_wrapper__init__,
_numpy_type=numpy_type
))
# this tricks matlab into accepting our new type
t.__module__ = matlab_type.__module__
_wrappers[numpy_type] = t
_define_wrapper(matlab.double, np.double)
_define_wrapper(matlab.single, np.single)
_define_wrapper(matlab.uint8, np.uint8)
_define_wrapper(matlab.int8, np.int8)
_define_wrapper(matlab.uint16, np.uint16)
_define_wrapper(matlab.int16, np.int16)
_define_wrapper(matlab.uint32, np.uint32)
_define_wrapper(matlab.int32, np.int32)
_define_wrapper(matlab.uint64, np.uint64)
_define_wrapper(matlab.int64, np.int64)
_define_wrapper(matlab.logical, np.bool_)
def as_matlab(arr):
try:
cls = _wrappers[arr.dtype.type]
except KeyError:
raise TypeError("Unsupported data type")
return cls(arr)
到达这里所需的观察结果是:
type(x).__name__
并type(x).__module__
确定它是否理解类型._data
属性中不幸的是,matlab 在_data
内部没有有效地使用该属性,并且一次迭代一项而不是使用 pythonmemoryview
协议:(。因此,这种方法的速度增益是微不足道的。
scipy.io.savemat 或 scipy.io.loadmat 不适用于 matlab 数组 --v7.3。但好的部分是 matlab --v7.3 文件是 hdf5 数据集。因此可以使用多种工具读取它们,包括 numpy。
对于 python,您将需要h5py扩展,这需要您系统上的HDF5。
import numpy as np, h5py
f = h5py.File('somefile.mat','r')
data = f.get('data/variable1')
data = np.array(data) # For converting to numpy array
前段时间,我遇到了同样的问题,并编写了以下脚本,以便在交互式会话中来回复制和粘贴数组。显然只适用于小型数组,但我发现它比每次都通过文件保存/加载更方便:
The python library Darr allows you to save your Python numpy arrays in a self-documenting and widely readable format, consisting of just binary and text files. When saving your array, it will include code to read that array in a variety of languages, including Matlab. So in essence, it is just one line to save your numpy array to disk in Python, and then copy-paste the code from the README.txt to load it into Matlab.
Disclosure: I wrote the library.
不确定它是否算作“更简单”,但我找到了一个解决方案,可以从一个由 matlab 快速调用的 python 脚本创建的 numpy 数组中移动数据:
dump_reader.py(python 源代码):
import numpy
def matlab_test2():
np_a = numpy.random.uniform(low = 0.0, high = 30000.0, size = (1000,1000))
return np_a
dump_read.m(matlab 脚本):
clear classes
mod = py.importlib.import_module('dump_reader');
py.importlib.reload(mod);
if count(py.sys.path,'') == 0
insert(py.sys.path,int32(0),'');
end
tic
A = py.dump_reader.matlab_test2();
toc
shape = cellfun(@int64,cell(A.shape));
ls = py.array.array('d',A.flatten('F').tolist());
p = double(ls);
toc
C = reshape(p,shape);
toc
它依赖于这样一个事实,即与单元格/矩阵相比,matlabs double 似乎在数组上有效地工作。第二个技巧是以有效的方式将数据传递给matlabs double(通过pythons native array.array)。
PS 很抱歉发布了 necroposting,但我为此付出了很多努力,这个话题是最热门的话题之一。也许它可以帮助某人缩短挣扎的时间。
PPS 使用 Matlab R2016b + python 3.5.4 (64bit) 测试
在最新的 R2021a 中,您可以将 python numpy ndarray 传递给 double(),它会转换为原生 matlab 矩阵,即使在控制台中调用 numpy 数组时,它也会在底部建议“使用 double 函数转换为 MATLAB 数组”
假设您有一个形状为 (365,10) 的 2D 每日数据,保存在 np 数组中五年,形状为np3Darrat
(5,365,10)。在 python 中保存你的 np 数组:
import scipy.io as sio #SciPy module to load and save mat-files
m['np3Darray']=np3Darray #shape(5,365,10)
sio.savemat('file.mat',m) #Save np 3D array
然后在 MATLAB 中将 np 3D 数组转换为 MATLAB 3D matix:
load('file.mat','np3Darray')
M3D=permute(np3Darray, [2 3 1]); %Convert numpy array with shape (5,365,10) to MATLAB matrix with shape (365,10,5)