将Numpy数组“转换”为Matlab,反之亦然

时间:2012-06-12 13:02:27

标签: python matlab numpy

我正在寻找一种将NumPy数组传递给Matlab的方法。

我设法通过使用scipy.misc.imsave将数组存储到图像中然后使用imread加载它来实现此目的,但这当然会导致矩阵包含0到256之间的值而不是'真正'的价值观。

将此矩阵的乘积除以256,并且原始NumPy数组中的最大值给出了正确的矩阵,但我觉得这有点单调乏味。

有更简单的方法吗?

8 个答案:

答案 0 :(得分:42)

当然,只需使用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

然后使用load test在matlab中加载它。

另外,正如@JAB建议的那样,您可以将内容保存到ascii制表符分隔文件(例如numpy.savetxt)。但是,如果你走这条路,你将被限制在2个维度。另一方面,ascii是普遍的交换格式。几乎所有东西都会处理分隔的文本文件。

答案 1 :(得分:8)

一个简单的解决方案,无需通过文件或外部库传递数据。

Numpy有一种方法可以将ndarrays转换为list,并且可以从列表中定义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()

答案 2 :(得分:4)

前段时间我遇到了同样的问题并编写了以下脚本,以便从交互式会话中轻松地来回复制和粘贴数组。显然只适用于小型数组,但我发现它比每次保存/加载文件更方便:

Matlab -> Python

Python -> Matlab

答案 3 :(得分:4)

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

答案 4 :(得分:2)

这是一种避免在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)

到达这里所需的观察结果是:

  • Matlab似乎只看type(x).__name__type(x).__module__来确定它是否理解类型
  • 似乎所有可索引的对象都可以放在._data属性中

不幸的是,matlab没有在内部有效地使用_data属性,而是一次遍历一个属性,而不是使用python memoryview协议:(。因此,速度增益在这种方法。

答案 5 :(得分:1)

不确定它是否算“更简单”但是我找到了一个解决方案,可以在一个python脚本中创建的numpy arrray中移动数据,该脚本很快被matlab调用:

dump_reader.py(python source):

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)。

P.S。对于necroposting感到遗憾,但我与它斗争很多,这个主题是最接近的点击之一。也许它可以帮助某人缩短挣扎的时间。

P.P.S。用Matlab R2016b + python 3.5.4(64bit)进行测试

答案 6 :(得分:1)

python 库 Darr 允许您以自文档化和广泛可读的格式保存 Python numpy 数组,该格式仅包含二进制文件和文本文件。保存数组时,它将包含使用各种语言(包括 Matlab)读取该数组的代码。所以本质上,在 Python 中将你的 numpy 数组保存到磁盘,然后从 README.txt 中复制粘贴代码以将其加载到 Matlab 中只需一行。

披露:我写了图书馆。

答案 7 :(得分:0)

假设您有一个形状为 (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)