逐行构造pyarrow table的最快方法
Fastest way to construct pyarrow table row by row
我有一个大字典,我想遍历它来构建一个 pyarrow table。字典的值是不同类型的元组,需要解包并存储在最终的 pyarrow table 中的单独列中。我确实提前知道架构。键也需要存储为一列。我在下面有一个逐行构造 table 的方法 - 还有另一种更快的方法吗?对于上下文,我想将一个大字典解析为一个 pyarrow table 以写出到一个镶木地板文件。与 CPU 时间相比,RAM 的使用不是那么令人担忧。我不想下拉到箭头 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
由于模式是提前知道的,您可以为每一列创建一个列表并构建一个包含列名和列值 对的字典。
%%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 s ± 236 ms per loop (mean ± std. dev. of 10 runs, 1 loop each)
我也在玩pyarrow。
对我来说,在您的代码中,数据准备阶段(随机等)似乎是最耗时的部分。
所以可能首先尝试将数据转换为数组的字典,然后将它们提供给 Arrow Table.
请看,我根据您的数据和 %%timeit
-ing 仅 Table 人口阶段制作示例。但是用 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 次 - table 填充了令人难以置信的 15 毫秒 :) 可能是由于缓存。
并修改了 1000 行,如 col1*integer 批处理 1000 次 - 33.3 ms,这看起来也不错。
我的样本notebook is here
PS。我想知道 numba jit 是否有帮助,但似乎只会让时间变得更糟。
我有一个大字典,我想遍历它来构建一个 pyarrow table。字典的值是不同类型的元组,需要解包并存储在最终的 pyarrow table 中的单独列中。我确实提前知道架构。键也需要存储为一列。我在下面有一个逐行构造 table 的方法 - 还有另一种更快的方法吗?对于上下文,我想将一个大字典解析为一个 pyarrow table 以写出到一个镶木地板文件。与 CPU 时间相比,RAM 的使用不是那么令人担忧。我不想下拉到箭头 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
由于模式是提前知道的,您可以为每一列创建一个列表并构建一个包含列名和列值 对的字典。
%%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 s ± 236 ms per loop (mean ± std. dev. of 10 runs, 1 loop each)
我也在玩pyarrow。 对我来说,在您的代码中,数据准备阶段(随机等)似乎是最耗时的部分。 所以可能首先尝试将数据转换为数组的字典,然后将它们提供给 Arrow Table.
请看,我根据您的数据和 %%timeit
-ing 仅 Table 人口阶段制作示例。但是用 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 次 - table 填充了令人难以置信的 15 毫秒 :) 可能是由于缓存。 并修改了 1000 行,如 col1*integer 批处理 1000 次 - 33.3 ms,这看起来也不错。
我的样本notebook is here
PS。我想知道 numba jit 是否有帮助,但似乎只会让时间变得更糟。