能否分块读取parquet文件?

24
例如,pandas的read_csv具有一个chunk_size参数,它允许read_csv返回CSV文件上的迭代器,以便我们可以分块读取它。
Parquet格式将数据存储在块中,但没有记录的方法可以像read_csv那样分块读取。
是否有一种方法可以分块读取parquet文件?

1
这个问题最好在GitHub或Apache Arrow邮件列表上提问。 - Wes McKinney
我在这里创建了一个增强请求: https://github.com/pandas-dev/pandas/issues/55973 - undefined
5个回答

27

你可以使用 pyarrow 的 iter_batches 方法,然后通过 to_pandas 方法将结果转换为 pandas DataFrame。

示例:

import pyarrow.parquet as pq

parquet_file = pq.ParquetFile('example.parquet')

for batch in parquet_file.iter_batches():
    print("RecordBatch")
    batch_df = batch.to_pandas()
    print("batch_df:", batch_df)

10
如果您的Parquet文件没有使用行组创建,则read_row_group方法似乎无法工作(只有一个组!)。
但是,如果您的Parquet文件被分区为Parquet文件目录,则可以使用fastparquet引擎,该引擎仅适用于单个文件,以读取文件,然后在pandas中连接文件或获取值并连接ndarrays。
import pandas as pd
from glob import glob
files = sorted(glob('dat.parquet/part*'))

data = pd.read_parquet(files[0],engine='fastparquet')
for f in files[1:]:
    data = pd.concat([data,pd.read_parquet(f,engine='fastparquet')])

1
这种方法唯一的问题是,如果使用pandas修改parquet文件,则用pyspark无法读取。我尝试创建新列或修改现有列中的值,但两个实验都以“校验和错误”的形式失败了。 - Sokolokki

5
我不确定是否可以直接使用pandas进行操作,但是pyarrow提供了read_row_group方法。通过这个方法得到的Table可以使用to_pandas转换为pandas dataframe。
在pyarrow 3.0版本中,新增了一个iter_batches方法,可以使用它来处理数据。

read_row_group仅保证从Parquet文件中读取单个行“组”,而不是行。 - WY Hsu

2

这是一个老问题,但如果您想要在不使用concat的情况下阅读所有块,则以下内容适用于我:

pd.read_parquet("chunks_*", engine="fastparquet")

或者如果你想阅读特定的块,可以尝试:

pd.read_parquet("chunks_[1-2]*", engine="fastparquet")

(这样你只会读取前两个块,也不需要指定引擎)


这只在文件被物理分区的情况下才有效吗? - xiaodai
物理分区是什么意思?如果您指的是由Dask等工具创建的某些分区,那么是的,它可以工作。 如果这种方法不适用于您,您可以尝试: pd.read_parquet(“your_parquet_path /”)或 pd.read_parquet(“your_parquet_path / *”),这取决于您使用的Pandas版本。 - George Farah

0

你不能在一个parquet文件上使用generator/iterator因为它是一个压缩文件。你需要先完全解压它。


2
不,您可以部分解压缩,因为压缩数据以流顺序存储。pyarrow支持使用iter_batches()完成这一点,并且分配的内存量与部分解压缩是一致的。 - hdante
1
更正:我认为我错了,实际上 pyarrow 在使用 iter_batches() 返回切片之前会先解压整个行组。 - hdante

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接