【问题标题】:Set type in pytables在 pytables 中设置类型
【发布时间】:2013-12-09 18:33:56
【问题描述】:

我有以下形式的数据:

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

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

`label in row`

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

【问题讨论】:

    标签: python hdf5 pytables


    【解决方案1】:

    您只有最大 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)]
    

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

    此外,由于标签会被重复使用,尤其是空字符串标签,我强烈建议您启用压缩。

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

    通过压缩和映射到/从整数,这可能是您可以获得的最快和最小的。

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

    【讨论】:

      猜你喜欢
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 2019-11-18
      • 2021-12-25
      • 1970-01-01
      • 2010-09-07
      • 1970-01-01
      • 2014-08-01
      相关资源
      最近更新 更多