【问题标题】:Fastest way to construct pyarrow table row by row逐行构造pyarrow表的最快方法
【发布时间】:2020-01-16 05:49:37
【问题描述】:

我有一个大字典,我想遍历它来构建一个 pyarrow 表。字典的值是不同类型的元组,需要解包并存储在最终 pyarrow 表中的单独列中。我确实提前知道架构。键也需要存储为一列。我在下面有一种方法可以逐行构造表格 - 还有另一种更快的方法吗?对于上下文,我想将一个大字典解析为一个 pyarrow 表以写入一个镶木地板文件。 RAM 使用比 CPU 时间更重要。我不想下拉到箭头 C++ API。

import pyarrow as pa
import random
import string 
import time

large_dict = dict()

for i in range(int(1e6)):
    large_dict[i] = (random.randint(0, 5), random.choice(string.ascii_letters))


schema = pa.schema({
        "key"  : pa.uint32(),
        "col1" : pa.uint8(),
        "col2" : pa.string()
   })

start = time.time()

tables = []
for key, item in large_dict.items():
    val1, val2 = item
    tables.append(
            pa.Table.from_pydict({
                    "key"  : [key],
                    "col1" : [val1],
                    "col2" : [val2]
                }, schema = schema)

            )

table = pa.concat_tables(tables)
end = time.time()
print(end - start) # 22.6 seconds on my machine

【问题讨论】:

    标签: python pyarrow apache-arrow


    【解决方案1】:

    我也在玩 pyarrow。 对我来说,您的代码数据准备阶段(随机等)似乎是最耗时的部分。 所以可能首先尝试将数据转换为数组的字典,然后将它们提供给箭头表。

    请看,我根据您的数据和%%timeit-ing 仅表填充阶段进行示例。但是用RecordBatch.from_arrays() 和三个数组组成的数组来做。

    I = iter(pa.RecordBatch.\
             from_arrays(
                          get_data(l0, l1_0, l2, i),
                          schema=schema) for i in range(1000)
            )
    
    T1 = pa.Table.from_batches(I, schema=schema)
    

    使用静态数据集 1000 行批处理 1000 次 - 表填充了令人难以置信的 15 毫秒 :) 由于缓存可能。 并且修改了 1000 行,例如 col1*integer 批处理 1000 次 - 33.3 ms,这看起来也不错。

    我的样本notebook is here

    附言。我想知道 numba jit 是否会有所帮助,但似乎它只会让时间变得更糟。

    【讨论】:

      【解决方案2】:

      由于提前知道架构,您可以为每一列创建一个列表并构建一个列名和列值对的字典。

      %%timeit -r 10
      import pyarrow as pa
      import random
      import string 
      import time
      
      large_dict = dict()
      
      for i in range(int(1e6)):
          large_dict[i] = (random.randint(0, 5), random.choice(string.ascii_letters))
      
      
      schema = pa.schema({
              "key"  : pa.uint32(),
              "col1" : pa.uint8(),
              "col2" : pa.string()
        })
      
      keys = []
      val1 = []
      val2 = []
      for k, (v1, v2) in large_dict.items():
        keys.append(k)
        val1.append(v1)
        val2.append(v2)
      
      table = pa.Table.from_pydict(
          dict(
              zip(schema.names, (keys, val1, val2))
          ),
          schema=schema
      )
      

      每个循环 2.92 秒 ± 236 毫秒(平均值 ± 标准偏差。10 次运行,每个循环 1 个)

      【讨论】:

      • 谢谢,这样更快。你会期望使用 pyarrow 数组而不是列表有什么好处吗?我提前知道元素的数量,所以可以预先分配。
      • 这应该证明是相似的性能。 pyarrow 隐式将原生 python 列表转换为数组 github.com/apache/arrow/blob/…
      • pyarrow 数组是不可变的,所以你很难附加到它们。但是你可以使用numpyndarray,这应该比python列表更快。
      猜你喜欢
      • 2019-04-08
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 2018-12-05
      • 1970-01-01
      • 2018-07-10
      • 2021-12-08
      相关资源
      最近更新 更多