使用Python Pytables加载Matlab稀疏矩阵

时间:2011-12-09 15:43:02

标签: python matlab numpy scipy sparse-matrix

我最初问了一个相关的问题here,但似乎并没有真正得到任何结果。也许如果我更具体地改写它的一部分,它可能有帮助......

我使用Matlab的稀疏格式存储文件(HDF5,csc I 相信),我正在尝试使用Pytables直接对它们进行操作, 但尚未成功。使用h5py我可以执行以下操作:

# Method 1: uses h5py (WORKS)
f1 = h5py.File(fname)
data = f1['M']['data']
ir = f1['M']['ir']
jc = f1['M']['jc']
M = scipy.sparse.csc_matrix((data, ir, jc))

但如果我尝试在Pytables中做同等的事情:

# Method 2: uses pyTables (DOESN'T WORK)
f2 = tables.openFile(fname)
data = f2.root.M.data
ir = f2.root.M.ir
jc = f2.root.M.jc
M = scipy.sparse.csc_matrix( (data,ir,jc) )

这失败了(经过漫长的等待)错误:

TypeError                                 Traceback (most recent call last)

/home/tdiethe/BMJ/<ipython console> in <module>()

/usr/lib/python2.6/dist-packages/scipy/sparse/compressed.pyc in __init__(self, arg1, shape, dtype, copy, dims, nzmax)
    56                     self.indices = np.array(indices, copy=copy)
    57                     self.indptr  = np.array(indptr, copy=copy)
---> 58                     self.data    = np.array(data, copy=copy, dtype=getdtype(dtype, data))
    59                 else:
    60                     raise ValueError, "unrecognized %s_matrix constructor usage" %\

/usr/lib/python2.6/dist-packages/scipy/sparse/sputils.pyc in getdtype(dtype, a, default)
    69                 canCast = False
    70             else:
---> 71                 raise TypeError, "could not interpret data type"
    72     else:
    73         newdtype = np.dtype(dtype)

TypeError: could not interpret data type

查看f2

In [63]: f2.root.M.data
Out[63]: 
/M/data (CArray(4753606,), zlib(3)) ''
  atom := Float64Atom(shape=(), dflt=0.0)
  maindim := 0
  flavor := 'numpy'
  byteorder := 'little'
  chunkshape := (8181,)

In [64]: f2.root.M.ir
Out[64]: 
/M/ir (CArray(4753606,), zlib(3)) ''
  atom := UInt64Atom(shape=(), dflt=0)
  maindim := 0
  flavor := 'numpy'
  byteorder := 'little'
  chunkshape := (8181,)

In [65]: f2.root.M.jc
Out[65]: 
/M/jc (CArray(133339,), zlib(3)) ''
  atom := UInt64Atom(shape=(), dflt=0)
  maindim := 0
  flavor := 'numpy'
  byteorder := 'little'
  chunkshape := (7843,)

我有两个问题:

  • 如何使用pytables加载此文件
  • 我是否需要执行转换为scipy稀疏矩阵以便能够对其执行操作,或者我是否可以直接对磁盘文件执行操作(矩阵乘法等...) - 即无需加载文件进入内存(如果没有使用pytables的意义?)?

1 个答案:

答案 0 :(得分:3)

我在原帖中错过了这个,但我认为你的问题出在PyTables的设计中,它在底层数据之上提供了额外的抽象层次。

请考虑以下事项:

>>> import tables
>>> import numpy as np

>>> h5_file = tables.openFile(fname)
>>> data = f2.root.M.data

此时data不是numpy数组:

>>> type(data)
tables.array.Array

>>> isinstance(data, np.ndarray)
False

tables.array.Array会立即加载基础数组,或立即显示类似数组的功能。当您尝试使用这些类型的对象在scipy中创建稀疏数组时,这就是导致错误的原因。

data生成的PyTables对象旨在通过其他命令提供对数据的访问(即您通过使用花哨的索引[...]来实现)。在此方法中,您可以通过执行data[:]data.read()来访问部分数据或所有数据。只有在这一点上才会生成熟悉的numpy数组。

有关tables.array.Array课程的详情,请参阅http://pytables.github.com/usersguide/libref.html#the-array-classhttp://www.pytables.org/moin/HowToUseGetting actual data部分,了解有关访问基础数据的示例。

比较pyh5产生更多类似数组的对象,但仍不是numpy数组。考虑:

>>> import pyh5
>>> f1 = h5py.File(fname)
>>> data = f1['M']['data']
>>> type(data)
h5py._hl.dataset.Dataset
>>> isinstance(data, np.ndarray)
>>> False

但是,您可以numpy立即对data进行scipy操作,例如np.cos(data)data + np.arange(len(data))data等更简单的操作。 numpy对象似乎还有一些熟悉的shape类似属性(即numpy.ndarray),并且基础数据(data.value)存储在pyh5。但是,我对PyTables并不熟悉,因为我自己没有使用它,所以我不确定这方面的限制是什么。

一般来说,pyh5pyh5似乎有不同的设计目标,因此应以不同的方式使用。 PyTables为HDF文件提供了类似Numpy的界面,而pyh5提供了更复杂的数据库操作。请参阅PyTables,{{1}}文档和Enthought邮件列表中对差异的讨论: