使用Python Pytables加载Matlab稀疏矩阵

3
我最初在此处提出了一个相关的问题,但似乎没有得到有效解答。如果我具体地重述一部分内容,也许会有所帮助。我有使用Matlab稀疏格式(HDF5,我认为是csc)存储的文件,并尝试使用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的意义是什么)?

这些错误是来自于scipy。你能否检查一下仅使用numpy对datairjc进行操作的能力。Numpy对数据(即dtype、shape等)有何看法?结果是否符合预期?它们是否与该调用签名在“scipy.sparse.csc_matrix”中所期望的相对应? - dtlussier
啊,是的,看起来我只需要:M = sparse.csc_matrix( (f2.root.M.data[...], f2.root.M.ir[...], f2.root.M.jc[...]) )但第二个问题我还不确定。看起来在PyTables上只能进行逐元素操作? - tdc
1个回答

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中的稀疏数组时出现错误的原因。
相反,PyTables生成的data对象旨在通过附加命令(即使用高级索引[...])提供对数据的访问。通过执行data[:]data.read(),您可以访问部分或全部数据。只有在此时才会产生熟悉的numpy数组。
有关tables.array.Array类的更多信息,请参见http://pytables.github.com/usersguide/libref.html#the-array-classhttp://www.pytables.org/moin/HowToUse中的获取实际数据部分,其中包括访问底层数据的示例。

相比之下,pyh5 生成更多类似于数组的对象,但仍不是 numpy 数组。考虑以下内容:

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

然而,您可以立即对data执行numpy操作,就像您调用scipy一样,或者执行更简单的操作,例如np.cos(data)data + np.arange(len(data))。此外,data对象似乎具有一些熟悉的numpy属性(即shape),底层数据(一个numpy.ndarray)存储在data.value中。然而,我不熟悉pyh5,因为我自己没有使用过它,所以我不确定在这方面的限制是什么。
总的来说,PyTablespyh5具有不同的设计目标,因此应该以不同的方式使用。 pyh5为HDF文件提供了更类似于Numpy的接口,而PyTables则提供了更复杂的类似数据库的操作。请参见pyh5PyTables文档和Enthought邮件列表上有关差异的讨论:

非常有用的答案,谢谢。我正在慢慢掌握这个!我认为PyTables将为我们的项目提供一些有用的功能,因为可扩展性很重要。 - tdc

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