处理parquet文件的核心工具是pyarrow库,它提供高效的数据读写能力,尤其适合大规模数据集。1. 写入parquet文件需先将pandas dataframe转换为pyarrow table,再使用pq.write_table()写入,可设置压缩方式如snappy、gzip等;2. 读取parquet文件使用pq.read_table()加载为arrow table,再通过to_pandas()转回dataframe;3. parquet相比csv的优势在于列式存储,支持列投影、高效压缩、复杂数据类型和谓词下推,显著提升i/o效率和查询性能;4. 处理大规模数据时的关键优化包括:使用列投影减少内存占用、利用谓词下推过滤数据、采用分区存储结构、启用内存映射减少加载开销;5. pyarrow与pandas无缝集成,支持零拷贝转换,并作为pandas读写parquet的后端引擎;6. 在pyspark中,pyarrow加速topandas()操作和pandas udf的执行,大幅提升jvm与python间的数据交换效率。因此,pyarrow不仅是parquet操作的首选工具,更是连接python数据生态各组件的高性能数据总线,完整支撑现代数据处理流程。

Python操作Apache Parquet文件,核心工具是
pyarrow
说实话,处理Parquet文件,
pyarrow
写入Parquet文件: 通常,我们手里会有一些数据,比如一个Pandas DataFrame。要把这些数据存成Parquet,流程其实挺直接的。
数据准备: 假设我们有一个DataFrame。
立即学习“Python免费学习笔记(深入)”;
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
import numpy as np
# 模拟一些数据
data = {
'id': range(10000),
'name': [f'User_{i}' for i in range(10000)],
'value': np.random.rand(10000),
'category': np.random.choice(['A', 'B', 'C'], 10000)
}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df.head())Pandas DataFrame转为Arrow Table: 这是关键一步,
pyarrow
Table
# 将Pandas DataFrame转换为PyArrow Table
table = pa.Table.from_pandas(df)
print("\nPyArrow Table Schema:")
print(table.schema)写入Parquet文件: 使用
pyarrow.parquet.write_table
# 写入Parquet文件
output_path = 'my_data.parquet'
pq.write_table(table, output_path, compression='snappy', version='2.0')
print(f"\n数据已成功写入到 {output_path}")snappy
gzip
brotli
读取Parquet文件: 读取就更简单了,基本上就是指定文件路径。
读取Parquet文件到Arrow Table:
# 从Parquet文件读取数据
read_table = pq.read_table(output_path)
print(f"\n从 {output_path} 读取的PyArrow Table:")
print(read_table.to_pandas().head())Arrow Table转回Pandas DataFrame(如果需要):
# 转换回Pandas DataFrame
read_df = read_table.to_pandas()
print("\n转换回Pandas DataFrame:")
print(read_df.head())
print(f"读取的数据行数:{len(read_df)}")这就是一个基本的读写流程。你会发现,整个过程非常直观,而且在后台,
pyarrow
这个问题问得好,很多人一开始都会纠结用什么格式存储数据。说实话,Parquet相比CSV,那简直是质的飞跃,尤其是在大数据场景下。
最核心的区别在于:Parquet是列式存储,而CSV是行式存储。 这听起来有点抽象,但实际影响巨大。
想象一下,CSV文件就是一行一行地记录数据,每行是一个完整的记录。这种方式对人类阅读很友好,但对计算机处理大规模数据就没那么高效了。如果你只想读取某个特定列的数据,CSV文件也得把整行都读进来,然后从中提取出你想要的列,这无疑是浪费IO和内存。
Parquet则不然,它把每一列的数据单独存储。这意味着什么?
pyarrow
WHERE category = 'A'
pyarrow
所以,如果你只是处理几百行的小数据,CSV可能还行。但一旦数据量上去,或者你需要频繁地对特定列进行分析,Parquet的优势就会变得非常明显。它更适合数据分析、机器学习等场景,是现代数据湖和数据仓库的基石之一。
处理大规模Parquet数据时,光知道读写是不够的,你还得知道怎么读写得更“聪明”。
pyarrow
列投影(Column Projection): 这可能是最简单也最有效的优化。正如我前面提到的,Parquet是列式存储。如果你只需要数据集中的几列,那么在读取时就明确告诉
pyarrow
# 只读取 'id' 和 'value' 两列
selected_columns_table = pq.read_table(output_path, columns=['id', 'value'])
print("\n只读取指定列:")
print(selected_columns_table.to_pandas().head())
print(f"读取的列:{selected_columns_table.column_names}")这能显著减少内存占用和I/O开销,尤其当你的Parquet文件有上百列,但你只关心其中几列时,效果非常显著。
谓词下推(Predicate Pushdown)/ 行过滤(Row Filtering): 如果你在读取数据时有过滤条件,把这些条件传递给
pyarrow
# 假设我们只想读取 category 为 'A' 的数据
# 过滤条件以 (column, operator, value) 的元组列表形式表示
filtered_table = pq.read_table(output_path, filters=[('category', '=', 'A')])
print("\n应用过滤条件后:")
print(filtered_table.to_pandas().head())
print(f"过滤后数据行数:{len(filtered_table.to_pandas())}")pyarrow
使用分区(Partitioning): 在实际的大数据场景中,Parquet文件常常是按某个或多个列进行分区的。比如,按日期分区:
data/year=2023/month=01/day=01/part-0.parquet
pyarrow
# 模拟分区写入
# df['year'] = 2023
# pq.write_to_dataset(table, root_path='my_partitioned_data', partition_cols=['category'])
# print("\n数据已按 'category' 分区写入。")
# 从分区数据集读取
# read_partitioned_table = pq.read_table('my_partitioned_data', filters=[('category', '=', 'B')])
# print("\n从分区读取并过滤:")
# print(read_partitioned_table.to_pandas().head())当你读取分区数据时,如果你在
filters
pyarrow
内存映射(Memory Mapping): 在某些情况下,特别是文件很大但你想快速访问时,可以使用内存映射。这可以让操作系统直接将文件内容映射到进程的虚拟地址空间,而不是先完全读入内存。
# read_table(output_path, memory_map=True) # 这种方式对于只读操作,且文件大小超过物理内存时,可以避免一次性加载所有数据, # 操作系统会按需加载文件页面。
这通常在数据处理流程中,你需要快速访问文件中的一部分,而不是全部加载时比较有用。
这些技巧结合起来,能让
pyarrow
pyarrow
与Pandas的无缝集成: 这是最常见也是最直接的协同方式。
pyarrow
from_pandas()
to_pandas()
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
# Pandas DataFrame -> PyArrow Table
df_example = pd.DataFrame({'col1': [1, 2, 3], 'col2': ['a', 'b', 'c']})
arrow_table = pa.Table.from_pandas(df_example)
print("Pandas DataFrame 转 PyArrow Table:\n", arrow_table)
# PyArrow Table -> Pandas DataFrame
df_from_arrow = arrow_table.to_pandas()
print("\nPyArrow Table 转 Pandas DataFrame:\n", df_from_arrow)这种转换非常高效,因为
pyarrow
在读写Parquet文件时,你甚至可以直接用Pandas的
read_parquet
to_parquet
pyarrow
# Pandas直接读写Parquet,内部使用pyarrow
df_example.to_parquet('pandas_pyarrow.parquet', engine='pyarrow', compression='snappy')
read_df_pandas = pd.read_parquet('pandas_pyarrow.parquet', engine='pyarrow')
print("\nPandas通过pyarrow读写Parquet:")
print(read_df_pandas.head())这种紧密的集成,让数据科学家和分析师可以继续使用他们熟悉的Pandas API,同时享受到
pyarrow
与Apache Spark (PySpark) 的深度融合:
pyarrow
pyarrow
toPandas()
toPandas()
pyarrow
pyarrow
# 伪代码,Spark环境下的操作
# from pyspark.sql import SparkSession
# spark = SparkSession.builder.appName("PyArrowSpark").getOrCreate()
# spark.conf.set("spark.sql.execution.arrow.pyspark.enabled", "true") # 启用Arrow优化
# spark_df = spark.createDataFrame(df) # 从Pandas DataFrame创建Spark DataFrame
# pandas_df_from_spark = spark_df.toPandas() # 此时会利用Arrow进行优化
# spark.stop()Pandas UDFs: 在PySpark中,Pandas UDFs允许你编写Python函数,这些函数以Pandas Series或DataFrame作为输入和输出,并在Spark集群上以矢量化的方式执行。
pyarrow
# 伪代码,Pandas UDF示例
# from pyspark.sql.functions import pandas_udf, PandasUDFType
# from pyspark.sql.types import LongType
#
# @pandas_udf("long", PandasUDFType.SCALAR)
# def multiply_by_two(series: pd.Series) -> pd.Series:
# return series * 2
#
# spark_df.withColumn("new_col", multiply_by_two(spark_df["value"]))可以说,没有
pyarrow
总而言之,
pyarrow
以上就是Python如何操作Apache Parquet?pyarrow高效读写的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号