如何高效地将Matlab引擎数组转换为numpy的ndarray?

13

我目前正在一个项目中工作,需要使用遗留的Matlab代码(使用Matlab引擎)完成一些处理步骤,其余部分使用Python(numpy)。

我注意到将Matlab的matlab.mlarray.double转换为numpy的numpy.ndarray结果似乎非常缓慢。

下面是一些示例代码,用于从另一个ndarray、列表和mlarray创建一个包含1000个元素的ndarray:

import timeit
setup_range = ("import numpy as np\n"
               "x = range(1000)")
setup_arange = ("import numpy as np\n"
                "x = np.arange(1000)")
setup_matlab = ("import numpy as np\n"
                "import matlab.engine\n"
                "eng = matlab.engine.start_matlab()\n"
                "x = eng.linspace(0., 1000.-1., 1000.)")
print 'From other array'
print timeit.timeit('np.array(x)', setup=setup_arange, number=1000)
print 'From list'
print timeit.timeit('np.array(x)', setup=setup_range, number=1000)
print 'From matlab'
print timeit.timeit('np.array(x)', setup=setup_matlab, number=1000)

需要以下时间:

From other array
0.00150722111994
From list
0.0705359556928
From matlab
7.0873282467

转换时间比从列表中转换长大约100倍。

有没有什么方法可以加快转换速度?


RobR的回答更为通用,适用于N(>2)维数组,请参考。 - Abhijat Biswas
2个回答

16

我在发布问题后不久就找到了解决方案。

对于一维数组,只需访问Matlab数组的_data属性。

import timeit
print 'From list'
print timeit.timeit('np.array(x)', setup=setup_range, number=1000)
print 'From matlab'
print timeit.timeit('np.array(x)', setup=setup_matlab, number=1000)
print 'From matlab_data'
print timeit.timeit('np.array(x._data)', setup=setup_matlab, number=1000)

打印
From list
0.0719847538787
From matlab
7.12802865169
From matlab_data
0.118476275533

对于多维数组,你需要在操作后重新整形数组。对于二维数组,这意味着调用:
np.array(x._data).reshape(x.size[::-1]).T

1
如果数据比较复杂,那么使用 _real 和 _imag 属性(而不是 _data)。 - jayann
或者等价于:np.array(x._data).reshape(x.size, order='F') - seralouk
稍微更快 - seralouk
这个解决方案似乎在Matlab R2022a中不再起作用。已提交支持请求。 - Peter N. Steinmetz
1
从MATLAB R2022a及更高版本开始,您可以直接将MATLAB对象传递到NumPy构造函数中,而不是使用未记录的_data属性。考虑到多维数组的实现现在快了数个数量级(请参见R2022a发行说明),任何解决方法都是不必要的。在将“x._data”替换为“x”后,以下是我从本文主要部分的代码中获得的输出:`来自其他数组` `0.0007055000000000256` `来自列表` `0.09001790000000004` `来自MATLAB` `0.005489099999998359` - Alan
1
Matlab支持说明,在R2022a中,_data从Python数组更改为C++ Matlab数据数组对象,并且速度更快。他们提供了在此对象上调用的.noncomplex和.real和.imag函数,以以1-D格式检索底层数据。 - Peter N. Steinmetz

16

对于 2D 数组,Tim 的回答非常好,但将其调整为 N 维数组的方法是使用 np.reshape() 函数的 order 参数:

np_x = np.array(x._data).reshape(x.size, order='F')


我认为应该这样写:np_x = np.array(x._data).reshape(x.size, order='F').T - Ruslan Shaydulin
@RuslanShaydulin 不行,因为 order='F' 已经被明确定义了。 - seralouk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接