从.m Matlab文件中声明的矩阵创建numpy数组
一个同事留下了一些我想用Numpy分析的数据文件。
每个文件都是一个matlab文件,比如说 data.m
,里面的格式是这样的(当然实际内容会有很多列和行):
values = [-24.92 -23.66 -22.55 ;
-24.77 -23.56 -22.45 ;
-24.54 -23.64 -22.56 ;
];
这就是matlab中常用的显式矩阵创建语法。
我想问的是:从这些文件创建一个numpy数组的最实用方法是什么?
我可以考虑用一种“粗暴”或者“快速且简单”的方法,但如果有更直接的办法,我当然更愿意使用,比如说numpy的标准函数或者其他模块的函数。
补充说明:我注意到我的文件可能包含 NaN
值,所以我很可能会调整答案,使用 numpy.genfromtxt
而不是 numpy.loadtxt
。我计划在有了最终代码后尽快分享出来。
谢谢大家的帮助!
补充说明:我最后写出了以下代码,我用正则表达式提取了 []
之间的内容,并使用 genfromtxt
创建了一个numpy数组,以便处理NaN。一个更简短的解决方案是使用 fromstring
方法,这个方法不需要StringIO,但它无法处理NaN,而我的数据中有NaN :oP
#!/usr/bin/env python
# coding: utf-8
import numpy, re, StringIO
with open('data.m') as f:
s = re.search('\[(.*)\]', f.read(), re.DOTALL).group(1)
buf = StringIO.StringIO(s)
a = numpy.genfromtxt(buf, missing_values='NaN', filling_values=numpy.nan)
2 个回答
1
你可以把一个迭代器传给 np.genfromtxt
:
import numpy as np
import re
with open(filename, 'r') as f:
lines = (re.sub(r'[^-+.0-9 ]+', '', line) for line in f)
arr = np.genfromtxt(lines)
print(arr)
这样会得到
[[-24.92 -23.66 -22.55]
[-24.77 -23.56 -22.45]
[-24.54 -23.64 -22.56]]
2
这里有几个选项,虽然都不是内置的。
你可能觉得不可接受的解决方案
这个解决方案可能属于你所说的“快速且粗糙”的类型,但它可以为下一个解决方案铺路。
把 values = [
去掉,最后一行的 ];
也去掉,然后把所有的 ;
替换成空白,这样就得到了:
-24.92 -23.66 -22.55
-24.77 -23.56 -22.45
-24.54 -23.64 -22.56
然后你可以像下面这样使用 numpy 的 loadtxt
。
>>> import numpy as np
>>> A = np.loadtxt('data.m')
>>> A
array([[-24.92, -23.66, -22.55],
[-24.77, -23.56, -22.45],
[-24.54, -23.64, -22.56]])
你可能觉得可以接受的解决方案
在这个解决方案中,我们创建一个方法,把输入的数据转换成 numpy loadtxt
能接受的格式(实际上和上面的一样)。
import StringIO
import numpy as np
def convert_m(fname):
with open(fname, 'r') as fin:
arrstr = fin.read()
arrstr = arrstr.split('[', 1)[-1] # remove the content up to the first '['
arrstr = arrstr.rsplit(']', 1)[0] # remove the content after ']'
arrstr = arrstr.replace(';', '\n') # replace ';' with newline
return StringIO.StringIO(arrstr)
现在我们有了这个,接下来做以下操作。
>>> np.loadtxt(convert_m('data.m'))
array([[-24.92, -23.66, -22.55],
[-24.77, -23.56, -22.45],
[-24.54, -23.64, -22.56]])