Numpy 使用`table.where()检索与条件匹配的PyTables表行的索引`
我需要与表中给定条件(数十亿行)匹配的行的索引(作为numpy数组),这是我目前在代码中使用的行,它可以工作,但非常难看:Numpy 使用`table.where()检索与条件匹配的PyTables表行的索引`,numpy,pytables,Numpy,Pytables,我需要与表中给定条件(数十亿行)匹配的行的索引(作为numpy数组),这是我目前在代码中使用的行,它可以工作,但非常难看: indices = np.array([row.nrow for row in the_table.where("foo == 42")]) 这也需要半分钟,我相信创建列表是原因之一 我还没有找到一个优雅的解决方案,而且我还在与pytables文档作斗争,所以有人知道有什么神奇的方法可以让它更漂亮、更快吗?可能我缺少了一个特殊的查询关键字,因为我觉得pytables应该能
indices = np.array([row.nrow for row in the_table.where("foo == 42")])
这也需要半分钟,我相信创建列表是原因之一
我还没有找到一个优雅的解决方案,而且我还在与pytables文档作斗争,所以有人知道有什么神奇的方法可以让它更漂亮、更快吗?可能我缺少了一个特殊的查询关键字,因为我觉得pytables应该能够以numpy数组的形式返回匹配的行索引。我阅读了pytables的源代码,
where()
是用Cython实现的,但速度似乎不够快。下面是一个可以加速的复杂方法:
首先创建一些数据:
from tables import *
import numpy as np
class Particle(IsDescription):
name = StringCol(16) # 16-character String
idnumber = Int64Col() # Signed 64-bit integer
ADCcount = UInt16Col() # Unsigned short integer
TDCcount = UInt8Col() # unsigned byte
grid_i = Int32Col() # 32-bit integer
grid_j = Int32Col() # 32-bit integer
pressure = Float32Col() # float (single-precision)
energy = Float64Col() # double (double-precision)
h5file = open_file("tutorial1.h5", mode = "w", title = "Test file")
group = h5file.create_group("/", 'detector', 'Detector information')
table = h5file.create_table(group, 'readout', Particle, "Readout example")
particle = table.row
for i in range(1001000):
particle['name'] = 'Particle: %6d' % (i)
particle['TDCcount'] = i % 256
particle['ADCcount'] = (i * 256) % (1 << 16)
particle['grid_i'] = i
particle['grid_j'] = 10 - i
particle['pressure'] = float(i*i)
particle['energy'] = float(particle['pressure'] ** 4)
particle['idnumber'] = i * (2 ** 34)
# Insert a new particle record
particle.append()
table.flush()
h5file.close()
提供与给定条件匹配的行的索引“我确信创建列表是原因之一”-您是否已对仅迭代匹配行而不构建任何列表或数组所需的时间进行了基准测试?如果列表创建是这里的瓶颈,我会很惊讶。谢谢你的评论!是的,我已经做了基准测试,测试文件大约是14秒(仅列表理解)对27秒(列表理解+
numpy.array
),所以50%的计算时间是numpy.array
创建时间。索引的典型大小是多少,有多少RAM?这取决于,介于1e5和1e8之间。内存应该限制在1GB左右……你是说你的机器(VM?)只有1GB的可用内存吗?如果是这样的话,那么您可能会耗尽物理内存并进行交换。包含1e8 int64元素的numpy阵列将占用800Mb的空间。同时,您还在内存中保存该列表,其大小将略大于800Mb(您可以通过从生成器表达式而不是listcomp生成数组来避免这种情况,例如np.fromiter((row.nrow表示_表中的row.where(“foo==42”)、dtype=np.uint64)
)。
h5file = open_file("tutorial1.h5")
table = h5file.get_node("/detector/readout")
size = 10000
col = "energy"
buf = np.zeros(batch, dtype=table.coldtypes[col])
res = []
for start in range(0, table.nrows, size):
length = min(size, table.nrows - start)
data = table.read(start, start + batch, field=col, out=buf[:length])
tmp = np.where(data > 10000)[0]
tmp += start
res.append(tmp)
res = np.concatenate(res)