You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PyArrow提取Parquet数据并避免嵌套循环?读取格式差异解惑

问题描述

需要对大量大体积Parquet文件做数据分析,分析逻辑简单,但用Pandas时需要嵌套循环切片提取数据。以下是Pandas最小可复现示例(MWE):

import pandas as pd
import numpy as np

col1 = [1,5,8,6,4,5,3,8,5,8,9,6,4,5,6,7,2,89,6,65,5,8,5,8,65,6,4]
col2 = ['a','a','a','a','b','b','b','b','c','c','c','c','a','a','a','a','a','a','a','a','b','b','b','c','c','c','c']
col3 = [1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]

df = pd.DataFrame({'col1':col1, 'col2':col2, 'col3':col3})

for i in np.unique(df.col3):
    slice_1 = df[df.col3==i]
    
    for j in np.unique(slice_1.col2):
        slice_2 = slice_1[slice_1.col2==j]
        print(slice_2.col1.values[-1])

希望用PyArrow替代,但目前只能用嵌套循环实现类似切片过滤,想知道无需嵌套循环实现上述print功能的方法;另外,用pyarrow.parquet.read_table(data)读取实际Parquet数据时,输出格式为[['a','a','a','a',],['a','a','a','a','a','a','a']],和用pyarrow.Table.from_pandas(df)转换上述MWE数据得到的输出结构不同,想知道原因。

解决方案

1. 无嵌套循环实现分组取最后一个值

PyArrow支持直接对Table进行分组聚合操作,完全不需要嵌套循环。核心思路是按col3和col2分组,然后对col1取最后一个值,代码示例如下:

import pyarrow as pa

# 实际场景直接用read_table读取Parquet文件即可,此处为兼容示例先转Table
table = pa.Table.from_pandas(df)

# 按col3、col2分组,聚合col1的最后一个值
result = table.group_by(['col3', 'col2']).aggregate([('col1', 'last')])

# 遍历结果输出(也可转成Pandas DataFrame查看结构化结果)
for row in result.to_pylist():
    print(row['col1_last'])

该方法基于PyArrow的列式存储优化,内存占用和处理速度远优于Pandas的嵌套循环切片,尤其适合大文件场景。

2. 读取Parquet与from_pandas输出格式差异的原因

差异本质是实际Parquet文件的Schema与MWE中DataFrame的Schema完全不同:

  • pa.Table.from_pandas(df)转换得到的Table中,col2是扁平的字符串数组(每个元素为单个字符串);
  • 你读取的实际Parquet文件中,对应列是嵌套列表类型(ListArray),每个元素本身就是一个字符串列表,因此输出呈现嵌套数组格式。

可通过查看Schema确认:

parquet_table = pa.parquet.read_table("your_data.parquet")
print(parquet_table.schema)

若输出中对应列的类型为list<string>,则说明该列是嵌套列表结构,这就是两种输出格式不同的根源。

内容的提问来源于stack exchange,提问作者Sal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 06:45:57