我正在使用带有 Python 2.6 的 PyTables 2.2.1,我想创建一个包含可变长度嵌套数组的表。
我搜索了 PyTables 文档,教程示例 ( PyTables Tutorial 3.8 ) 展示了如何创建长度 = 1 的嵌套数组。但是对于这个示例,我将如何向数据 'info2/添加可变数量的行info3/x' 和 'info2/info3/y'?
为了更容易理解表结构,这是我自己开发的示例:
"""Desired Pytable output:
DIEM TEMPUS Temperature Data
5 0 100 Category1 <--||--> Category2
x <--| |--> y z <--|
0 0 0
2 1 1
4 1.33 2.67
6 1.5 4.5
8 1.6 6.4
5 1 99
2 2 0
4 2 2
6 2 4
8 2 6
5 2 96
4 4 0
6 3 3
8 2.67 5.33
Note that nested arrays have variable length.
"""
import tables as ts
tableDef = {'DIEM': ts.Int32Col(pos=0),
'TEMPUS': ts.Int32Col(pos=1),
'Temperature' : ts.Float32Col(pos=2),
'Data':
{'Category1':
{
'x': ts.Float32Col(),
'y': ts.Float32Col()
},
'Category2':
{
'z': ts.Float32Col(),
}
}
}
# create output file
fpath = 'TestDb.h5'
fh = ts.openFile(fpath, 'w')
# define my table
tableName = 'MyData'
fh.createTable('/', tableName, tableDef)
tablePath = '/'+tableName
table = fh.getNode(tablePath)
# get row iterator
row = table.row
for i in xrange(3):
print '\ni=', i
# calc some fake data
row['DIEM'] = 5
row['TEMPUS'] = i
row['Temperature'] = 100-i**2
for j in xrange(5-i):
# Note that nested array has variable number of rows
print 'j=', j,
# calc some fake nested data
val1 = 2.0*(i+j)
val2 = val1/(j+1.0)
val3 = val1 - val2
''' Magic happens here...
How do I write 'j' rows of data to the elements of
Category1 and/or Category2?
In bastardized pseudo-code, I want to do:
row['Data/Category1/x'][j] = val1
row['Data/Category1/y'][j] = val2
row['Data/Category2/z'][j] = val3
'''
row.append()
table.flush()
fh.close()
我在 PyTables 文档中没有发现任何迹象表明这样的结构是不可能的......但如果这样的结构实际上是不可能的,我有什么替代可变长度嵌套列的方法?
- 电子阵列? VL阵列?如果是,如何将这些数据类型集成到上述结构中?
- 还有其他想法吗?
非常感谢任何帮助!
使用附加信息进行编辑: 看来 PyTables 大师们已经解决了“这样的结构是否可能”的问题:
PyTables Mail Forum - Hierachical Datasets
那么有没有人想出一种方法来创建类似的 PyTable 数据结构?
再次感谢!
最佳答案
我有一个类似的任务:使用可变长度的数组转储固定大小的数据。
我首先尝试使用固定大小的 StringCol(64*1024) 字段来存储我的可变长度数据(它们总是小于 64K)。但它相当慢并且浪费了大量磁盘空间,尽管 blosc 压缩。
经过几天的调查,我得出了以下解决方案:
(剧透:我们将数组字段存储在单独的 EArray 实例中,每个数组字段一个 EArray)
- 我将固定大小的数据存储在常规 pytables 表中。
我向这些表添加了 2 个附加字段:arrFieldName_Offset 和 arrFieldName_Length:
class Particle(IsDescription): idnumber = Int64Col() ADCcount = UInt16Col() TDCcount = UInt8Col() grid_i = Int32Col() grid_j = Int32Col() pressure = Float32Col() energy = FloatCol() buffer_Offset = UInt32() # note this field! buffer_Length = UInt32() # and this one too!
我还为每个数组字段创建一个 EArray 实例:
datatype = StringAtom(1) buffer = h5file.createEArray('/detector', 'arr', datatype, (0,), "")
然后我添加对应于固定大小数据的行:
row['idnumber'] = ... ... row['energy'] = ... row['buffer_Offset'] = buffer.nrows # my_buf is a string (I get it from a stream) row['buffer_Length'] = len(my_buf) table.append(row)
哒哒!将缓冲区添加到数组中。
buffer.append(np.ndarray((len(my_buf),), buffer=my_buf, dtype=datatype))
这就是诀窍。在我的实验中,这种方法比存储参差不齐的固定大小数组(如 StringAtom(HUGE_NUMBER))快 2-10 倍,并且生成的数据库小几倍 (2-5x)
获取缓冲区数据很容易。假设 row 是您从数据库中读取的单行:
# Open array for reading buffer = h5file.createEArray('/detector', 'Particle.buffer', datatype, (0,), "") ... row = ... ... bufferDataYouNeed = buffer[ row['buffer_Offset'] : row['buffer_Offset'] + row['buffer_Length']]
关于python - 在 PyTables 中,如何创建可变长度的嵌套数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5366099/