8

我有一个大字典,我想遍历它来构建一个 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

4

2 回答 2

7

由于架构是提前知道的,因此您可以为每列制作一个列表并构建一个包含列名和列值对的字典。

%%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 个)

于 2019-09-14T22:12:01.390 回答
3

我也在玩 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,这看起来也不错。

我的示例笔记本在这里

PS。我想知道 numba jit 可能会有所帮助,但似乎它只会让时间变得更糟。

于 2019-10-18T17:51:05.307 回答