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

Posted

技术标签:

【中文标题】将 Numpy 数组“转换”为 Matlab,反之亦然【英文标题】:"Converting" Numpy arrays to Matlab and vice versa 【发布时间】:2012-06-15 08:53:23 【问题描述】:

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

我已经设法做到这一点,方法是使用 scipy.misc.imsave 将数组存储到图像中,然后使用 imread 加载它,但这当然会导致矩阵包含 0 到 256 之间的值而不是“真实”价值观。

取这个矩阵除以 256 的乘积,原始 NumPy 数组中的最大值给了我正确的矩阵,但我觉得这有点乏味。

有没有更简单的方法?

【问题讨论】:

我忘了,Matlab 允许解析文本文件吗?因为您可以将 numpy 数组格式化为字符串中的 Matlab 样式的数组,将它们写入文件,然后将数组读入 Matlab。 你考虑过 mlabwrap mlabwrap.sourceforge.net/#description 您确定不能完全在 numpy/scipy 中进行计算吗?只是想知道 我很确定我可以将 PLSM 算法的 Matlab 实现转换为 numpy,但是要解决由非同一个和函数差异引起的所有问题是非常时间的-消耗。感谢@JAB 的提示,它比先将其转换为图像更乏味。不过,我以后可能会遇到 3D 矩阵,所以 Joe 的解决方案适合我。 MATLAB可以读写HDF5格式,还有python库。 .. 【参考方案1】:

当然,只需使用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 数组保存到一个文件中,然后让 matlab 读取它,比如load('test.mat')? 将使用data.npzdata.npy 将不起作用?如果没有,为什么不呢? 谢谢你,正是我要找的。​​span> 【参考方案2】:

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

Numpy 有一种将 ndarray 转换为列表的方法,并且 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 维度。

np_a = np.array(mat_a._data.tolist())
np_a = np_a.reshape(mat_a.size).transpose()

【讨论】:

请注意,mat_a = matlab.double(np_a.tolist()) 可能非常低效/缓慢。对于 np 数组以外的任何内容,请选择 Joe Kington 的答案。见***.com/a/45284125/2524427【参考方案3】:

这是一个避免在 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 协议:(。所以这种方法的速度增益是微不足道的。

【讨论】:

加速应该是相当显着的。用这种方法我得到了大约 15 倍。 ***.com/a/45290997/4045774 @max9111:你有没有发现用array.array 包裹(就像你在那里做的那样)和不这样做(就像我在这里做的那样)有什么不同? 是的,您的版本更快;)。也许最好澄清一下您的解决方案实际上比 matlab.double(np_a.tolist()) 快得多。 对于您希望避免文件系统上的数据重复和任何 I/O 相关时间的情况,这似乎是最佳选择。 对于 100 x 100 x 100 阵列,此方法每次循环需要 2.73 ms ± 191 µs(平均值 ± 标准偏差,7 次运行,每次 100 次循环),但 matlab.double 需要 1.12每个循环 s ± 58.1 毫秒(平均值 ± 标准偏差。7 次运行,每次 1 个循环)。大约 400 倍加速...【参考方案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

【讨论】:

【参考方案5】:

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

Matlab -> Python

Python -> Matlab

【讨论】:

【参考方案6】:

不确定它是否算“更简单”,但我找到了一个解决方案,可以从一个由 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)。

附:很抱歉发布了 necroposting,但我为此付出了很多努力,这个话题是最热门的话题之一。也许它可以帮助某人缩短挣扎的时间。

附言使用 Matlab R2016b + python 3.5.4 (64bit) 测试

【讨论】:

【参考方案7】:

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

披露:我编写了库。

【讨论】:

有趣!如果您与编写该库的 Gabriel 相同,请添加披露信息。【参考方案8】:

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

【讨论】:

【参考方案9】:

在最新的 R2021a 中,您可以将 python numpy ndarray 传递给 double(),它将转换为本机 matlab 矩阵,即使在控制台中调用 numpy 数组时,它也会在底部建议“使用 double 函数转换为MATLAB 数组”

【讨论】:

以上是关于将 Numpy 数组“转换”为 Matlab,反之亦然的主要内容,如果未能解决你的问题,请参考以下文章

Numpy 排序比 Matlab 排序慢得多

将 numpy 数组转换为 CSV 字符串,将 CSV 字符串转换回 numpy 数组

如何将 numpy 数组列表转换为单个 numpy 数组?

将两个numpy数组转换为数据框

如何将numpy数组列表转换为numpy数组

将字符串转换为numpy数组