PyTables问题 - 迭代表子集时结果不同
我刚接触PyTables,想用它来处理从基于代理的建模模拟中生成的数据,这些数据存储在HDF5格式里。我正在处理一个39MB的测试文件,但遇到了一些奇怪的情况。下面是表格的结构:
/example/agt_coords (Table(2000000,)) ''
description := {
"agent": Int32Col(shape=(), dflt=0, pos=0),
"x": Float64Col(shape=(), dflt=0.0, pos=1),
"y": Float64Col(shape=(), dflt=0.0, pos=2)}
byteorder := 'little'
chunkshape := (20000,)
这是我在Python中访问它的方式:
from tables import *
>>> h5file = openFile("alternate_hose_test.h5", "a")
h5file.root.example.agt_coords
/example/agt_coords (Table(2000000,)) ''
description := {
"agent": Int32Col(shape=(), dflt=0, pos=0),
"x": Float64Col(shape=(), dflt=0.0, pos=1),
"y": Float64Col(shape=(), dflt=0.0, pos=2)}
byteorder := 'little'
chunkshape := (20000,)
>>> coords = h5file.root.example.agt_coords
现在事情变得奇怪了。
[x for x in coords[1:100] if x['agent'] == 1]
[(1, 25.0, 78.0), (1, 25.0, 78.0)]
>>> [x for x in coords if x['agent'] == 1]
[(1000000, 25.0, 78.0), (1000000, 25.0, 78.0)]
>>> [x for x in coords.iterrows() if x['agent'] == 1]
[(1000000, 25.0, 78.0), (1000000, 25.0, 78.0)]
>>> [x['agent'] for x in coords[1:100] if x['agent'] == 1]
[1, 1]
>>> [x['agent'] for x in coords if x['agent'] == 1]
[1, 1]
我不明白为什么当我遍历整个表格时,值会出现问题,而当我只取一小部分行时却没有。我相信这是我使用这个库时的错误,所以如果有人能帮我解决这个问题,我将非常感激。
1 个回答
7
在遍历Table
对象时,这个问题非常常见,很多人会感到困惑。
当你遍历一个Table
时,得到的不是每一项的数据,而是指向当前行的一个访问器。所以,使用
[x for x in coords if x['agent'] == 1]
你创建了一个行访问器的列表,这些访问器都指向表格的“当前”行,也就是最后一行。但是当你执行
[x["agent"] for x in coords if x['agent'] == 1]
时,你是在构建列表的过程中使用这个访问器。
要在构建列表时获取所有需要的数据,可以在每次迭代时使用这个访问器。这里有两种选择:
[x[:] for x in coords if x['agent'] == 1]
或者
[x.fetch_all_fields() for x in coords if x['agent'] == 1]
第一种方法会生成一个元组的列表,而第二种方法会返回一个NumPy的无类型对象。记得我没记错的话,第二种方法速度更快,但第一种方法可能更符合你的需求。
这里有一个来自PyTables开发者的好解释。在未来的版本中,打印一个行访问器对象可能不仅仅显示数据,而是说明它是一个行访问器对象。