在pytables中设置类型

时间:2013-12-07 01:07:59

标签: python hdf5 pytables

我的数据如下:

"blue red"
"blue magenta cyan"
"yellow red"
"black" 

每行中的最大元素数为10,但可能有数千个标签/类别/颜色。我想以某种方式在pytables列中插入这些数据,目的是以下列形式进行查询:

`label in row`

例如,返回包含blue标签的所有文档(结果将是前两行)。考虑到Pytables没有set数据类型这一事实,最有效的方法是什么?

1 个答案:

答案 0 :(得分:3)

您只有最大N=10的事实很棒。这意味着可以进行这些比较。你应该做的是有10个字符串列,其中每列是一个标签。如果一行的标签少于10个,则用空字符串填充。

这将允许您编写可在Table.where()Table.read_where()命令[1]中使用的高效查询表达式。假设列具有愚蠢的名称'col0','col1'等。因为字符串比较在numexpr中是精确的,并且因为没有本机集类型,所以必须显式展开相等比较:

cond = ("col0 == 'blue' | col1 == 'blue' | col2 == 'blue' | col3 == 'blue' | "
        "col4 == 'blue' | col5 == 'blue' | col6 == 'blue' | col7 == 'blue' | "
        "col8 == 'blue' | col9 == 'blue'")
rows = [row[:] for row in table.where(cond)]

幸运的是,很容易以编程方式构造cond字符串:

cond = " | ".join(["col{0} == 'blue'".format(i) for i in range(10)])

然而,你可以做的更多。字符串比较笨重而且速度慢。这是因为您的所有字符串都必须具有相同的大小,这意味着您的列大小由最长的标签决定。这导致了大量浪费的空间。相反,您应该与标签整数进行映射。然后你可以存储整数,快速比较这些。例如,使用列表索引:

labels = ['', 'blue', 'red', 'yellow', ...]
labels_to_idx = dict(zip(labels, range(len(labels))))
cond = " | ".join(["col{0} == '{1}'".format(i, labels_to_idx['blue']) 
                   for i in range(10)])
rows = [[labels[x] for x in row[:]] for row in table.where(cond)]

您甚至可以将标签列表存储在PyTables中作为EArray,这样您就可以确保始终获得相同的索引顺序,同时还可以扩展允许标签列表。

此外,由于标签将被重复使用,特别是空字符串标签,我高度建议您启用压缩。

不幸的是,由于列是索引的(而不是表),因此您无法索引这些查询。

通过对整数进行压缩和映射,这可能是您获得的最快和最小的。

  1. http://pytables.github.io/usersguide/libref/structured_storage.html?highlight=read_where#tables.Table.read_where