PyArrow 完整教程(Python 3.14)
版本环境 :Python 3.14 + PyArrow 24.0.0
教程定位:全功能覆盖、分章节、代码逐行注释、从入门到高阶,包含数据结构、IO、计算、列式操作、跨格式转换、内存管理、实战场景。
前置说明:PyArrow 是 Apache Arrow 的 Python 绑定,主打列式内存数据、高性能IO、多格式互通、零拷贝数据交换,是 Pandas、Dask、Ray、大数据生态的底层核心。
第一章 环境安装 & 基础入门
1.1 安装依赖
bash
# 安装指定版本 pyarrow 24.0.0
pip install pyarrow==24.0.0
# 可选扩展(文件格式、压缩、Parquet/ORC、S3 等)
pip install pyarrow[all]==24.0.0
1.2 版本校验 & 基础导入
python
# 导入核心模块
import pyarrow as pa
import pyarrow.compute as pc # 计算函数库
import pyarrow.parquet as pq # Parquet IO
import pyarrow.csv as pv # CSV IO
import pyarrow.feather as ft # Feather IO
import pyarrow.json as pj # JSON IO
import pyarrow.orc as po # ORC IO
# 逐行注释
# 1. 打印 PyArrow 版本,确认环境为 24.0.0
print(f"PyArrow 版本: {pa.__version__}")
# 2. 打印 Python 版本,确认 3.14
import sys
print(f"Python 版本: {sys.version}")
# 3. 查看系统支持的压缩算法
print("支持的压缩格式:", pa.compression_supported())
1.3 核心概念速览
- Arrow Array:单列列式数据(对标 Python list / NumPy array)
- Arrow Table:多列表格数据(对标 Pandas DataFrame)
- Schema:数据表结构、字段类型、元数据
- ChunkedArray:分块数组(超大内存数据分片存储)
- RecordBatch:批量行数据(流式处理核心)
第二章 数据类型(DataType)全详解
PyArrow 拥有完备的原生列式数据类型,是一切数据构建的基础。
2.1 基础原子类型
python
# ========== 逐行注释 ==========
# 1. 布尔类型
bool_type = pa.bool_()
print("布尔类型:", bool_type)
# 2. 整数类型(有符号/无符号,不同位宽)
int8 = pa.int8() # 8位有符号整型
int16 = pa.int16() # 16位有符号整型
int32 = pa.int32() # 32位有符号整型
int64 = pa.int64() # 64位有符号整型(最常用)
uint8 = pa.uint8() # 8位无符号整型
uint64 = pa.uint64()
print("整型示例:", int64, uint8)
# 3. 浮点类型
float16 = pa.float16()
float32 = pa.float32()
float64 = pa.float64() # 双精度浮点,默认浮点类型
print("浮点类型:", float64)
# 4. 字符串/二进制类型
string_type = pa.string() # UTF-8 字符串(推荐)
large_string = pa.large_string() # 大字符串(支持超长文本)
binary = pa.binary() # 原始二进制
large_binary = pa.large_binary()
print("字符串类型:", string_type)
# 5. 日期 & 时间类型
date32 = pa.date32() # 日期(天数偏移)
date64 = pa.date64() # 日期(毫秒偏移)
time32 = pa.time32('s') # 时间 单位:秒
time64 = pa.time64('ms')# 时间 单位:毫秒
timestamp = pa.timestamp('ns') # 时间戳 纳秒(最常用)
print("时间戳类型:", timestamp)
# 6. 十进制高精度数值(金融场景)
decimal128 = pa.decimal128(precision=18, scale=2) # 18位总长度,2位小数
print("十进制类型:", decimal128)
2.2 复合嵌套类型(数组、结构体、字典)
python
# ========== 逐行注释 ==========
# 1. 列表类型(一维数组)
list_type = pa.list_(pa.int64()) # 元素为int64的列表列
print("列表类型:", list_type)
# 2. 固定长度列表
fixed_list = pa.fixed_size_list(pa.float64(), 3) # 固定3个元素
print("定长列表:", fixed_list)
# 3. 结构体类型(类似字典/对象,多字段组合)
struct_type = pa.struct([
pa.field("name", pa.string()), # 字段1:name 字符串
pa.field("age", pa.int32()), # 字段2:age 整型
pa.field("score", pa.float64()) # 字段3:score 浮点
])
print("结构体类型:", struct_type)
# 4. 字典编码类型(低基数字符串,压缩优化)
dict_type = pa.dictionary(pa.int32(), pa.string())
print("字典类型:", dict_type)
# 5. 联合类型(多类型混合)
union_type = pa.union([pa.int64(), pa.string()])
print("联合类型:", union_type)
2.3 字段(Field) & 数据表结构(Schema)
Schema 定义整张表的字段、类型、是否可空、元数据。
python
# ========== 逐行注释 ==========
# 1. 定义单个字段:字段名 + 数据类型 + 是否允许空值(nullable)
field_name = pa.field("username", pa.string(), nullable=False)
field_age = pa.field("age", pa.int32(), nullable=True)
# 2. 构建表 Schema(整张表的结构)
table_schema = pa.schema([
field_name,
field_age,
pa.field("register_time", pa.timestamp('ns'))
])
# 3. 打印完整结构
print("数据表 Schema:")
print(table_schema)
# 4. 读取 Schema 单个字段
print("第一个字段名:", table_schema[0].name)
print("第一个字段类型:", table_schema[0].type)
# 5. 给 Schema 添加自定义元数据(字典格式)
meta = {"author": "pyarrow_demo", "version": "1.0"}
schema_with_meta = table_schema.with_metadata(meta)
print("带元数据的Schema:", schema_with_meta.metadata)
第三章 核心数据容器:Array / ChunkedArray
3.1 基础 Array 创建(单列数据)
Arrow Array 是列式存储最小单元,零拷贝、高性能。
python
# ========== 逐行注释 ==========
# 1. 从 Python List 创建 Array
arr1 = pa.array([1, 2, 3, 4, 5])
print("基础整型Array:", arr1)
print("Array 数据类型:", arr1.type)
print("元素个数:", arr1.length)
# 2. 包含空值(None)的 Array
arr_null = pa.array([10, None, 30, None, 50])
print("含空值Array:", arr_null)
print("空值数量:", arr_null.null_count)
# 3. 指定数据类型创建(强制类型转换)
arr_cast = pa.array([1.1, 2.2, 3.3], type=pa.float32())
print("指定浮点类型Array:", arr_cast, arr_cast.type)
# 4. 字符串 Array
str_arr = pa.array(["Alice", "Bob", "Charlie", None])
print("字符串Array:", str_arr)
# 5. 时间戳 Array
time_arr = pa.array([1718400000000000000, 1718500000000000000], type=pa.timestamp('ns'))
print("时间戳Array:", time_arr)
3.2 Array 常用属性 & 切片取值
python
# ========== 逐行注释 ==========
# 初始化测试数组
arr = pa.array([10, 20, 30, 40, 50, None])
# 1. 基础属性
print("是否包含空值:", arr.null_count > 0)
print("有效数据掩码(布尔数组,True=非空):", arr.is_valid())
print("空值掩码:", arr.is_null())
# 2. 单个元素取值(下标访问)
print("下标0元素:", arr[0])
print("下标-1元素(最后一个):", arr[-1])
# 3. 切片(和Python list一致,左闭右开)
slice1 = arr[1:4] # 取 下标1,2,3
print("切片 [1:4]:", slice1)
# 4. 转为 Python List / NumPy Array
py_list = arr.to_pylist()
np_arr = arr.to_numpy(na_value=0) # na_value:空值填充值
print("转为Python列表:", py_list)
print("转为NumPy数组:", np_arr)
3.3 ChunkedArray 分块数组(超大数据集)
当数据量极大、无法单块存放时,使用分块数组,支持无缝拼接、流式读取。
python
# ========== 逐行注释 ==========
# 1. 创建多个独立 Array 块
chunk1 = pa.array([1, 2, 3])
chunk2 = pa.array([4, 5, 6, 7])
chunk3 = pa.array([8, None, 10])
# 2. 组合为 ChunkedArray
chunked_arr = pa.chunked_array([chunk1, chunk2, chunk3])
print("分块数组整体:", chunked_arr)
print("总元素数:", chunked_arr.length)
print("分块数量:", chunked_arr.num_chunks)
# 3. 遍历每一个数据块
for idx, chunk in enumerate(chunked_arr.chunks):
print(f"第{idx}个块:", chunk)
# 4. 切片、转列表(用法同普通Array)
print("分块数组切片 [2:6]:", chunked_arr[2:6])
print("转为列表:", chunked_arr.to_pylist())
# 5. 合并分块为单块 Array(内存允许时使用)
merged_arr = chunked_arr.combine_chunks()
print("合并为单块Array:", merged_arr)
第四章 核心数据表:Table & RecordBatch
4.1 Table 创建(对标 Pandas DataFrame)
Table 是 PyArrow 最常用的多列表格结构,由多个列(Array/ChunkedArray)+ Schema 组成。
python
# ========== 逐行注释 ==========
# 1. 构造多列数据(每一列都是 Arrow Array)
col_name = pa.array(["Tom", "Jerry", "Lily", "Lucy"])
col_age = pa.array([22, 24, 21, 23])
col_score = pa.array([88.5, 92.0, 79.0, 85.5])
# 2. 方式1:字典方式创建 Table(最简单)
table1 = pa.Table.from_pydict({
"name": col_name,
"age": col_age,
"score": col_score
})
print("=== 字典创建 Table ===")
print(table1)
# 3. 查看 Table 基础信息
print("表行数:", table1.num_rows)
print("表列数:", table1.num_columns)
print("表 Schema:", table1.schema)
# 4. 方式2:从列表+字段名创建
table2 = pa.Table.from_arrays(
arrays=[col_name, col_age, col_score],
names=["name", "age", "score"]
)
print("\n=== 数组列表创建 Table ===")
print(table2)
# 5. 方式3:指定自定义 Schema 创建(强约束)
custom_schema = pa.schema([
pa.field("name", pa.string()),
pa.field("age", pa.int32()),
pa.field("score", pa.float64())
])
table3 = pa.Table.from_arrays([col_name, col_age, col_score], schema=custom_schema)
print("\n=== 自定义Schema创建 Table ===")
print(table3.schema)
4.2 Table 列操作、行切片、字段重命名
python
# ========== 逐行注释 ==========
# 复用上面的 table1
table = table1
# 1. 获取单列(按列名 / 按下标)
col_by_name = table["name"]
col_by_idx = table.column(1)
print("按列名取列:", col_by_name)
print("按下标取列(age):", col_by_idx)
# 2. 多列选取(子集表)
sub_table = table.select(["name", "score"])
print("\n选取多列后的子表:")
print(sub_table)
# 3. 行切片(截取部分行)
row_slice = table.slice(1, 3) # 从第1行开始,取3行
print("\n行切片 slice(1,3):")
print(row_slice)
# 4. 新增一列
new_col = pa.array([1, 2, 3, 4])
table_add = table.append_column("rank", new_col)
print("\n新增rank列:")
print(table_add)
# 5. 删除一列
table_drop = table.remove_column("score")
print("\n删除score列:")
print(table_drop)
# 6. 重命名列
rename_mapping = {"name": "username", "age": "user_age"}
table_rename = table.rename_columns(rename_mapping)
print("\n重命名列后Schema:")
print(table_rename.schema)
4.3 RecordBatch 记录批次(流式/分批处理)
RecordBatch 是行批次结构,多用于数据流、批量计算、网络传输,和 Table 结构高度兼容。
python
# ========== 逐行注释 ==========
# 1. 从数组创建 RecordBatch
batch = pa.RecordBatch.from_arrays(
[pa.array([1,2,3]), pa.array(["A","B","C"])],
names=["id", "tag"]
)
print("RecordBatch:")
print(batch)
print("Batch 行数:", batch.num_rows)
print("Batch 列数:", batch.num_columns)
# 2. RecordBatch 转 Table
batch_to_table = pa.Table.from_batches([batch])
print("\nBatch 转为 Table:")
print(batch_to_table)
# 3. Table 拆分为多个 RecordBatch(分批)
# 模拟大表,拆分每2行为一个batch
batches = table1.to_batches(max_chunksize=2)
print(f"\nTable 拆分为 {len(batches)} 个Batch")
for b in batches:
print("单个Batch:", b)
4.4 Table 拼接、合并、去重
python
# ========== 逐行注释 ==========
# 构造两张测试表
t1 = pa.Table.from_pydict({"id": [1,2], "val": [10,20]})
t2 = pa.Table.from_pydict({"id": [3,4], "val": [30,40]})
# 1. 垂直拼接(上下合并,行数增加)
table_concat = pa.concat_tables([t1, t2])
print("垂直拼接表:")
print(table_concat)
# 2. 简单去重(整行去重)
dup_table = pa.Table.from_pydict({"id":[1,1,2], "val":[10,10,20]})
dedup_table = dup_table.unique()
print("\n去重后:")
print(dedup_table)
第五章 计算函数库 pyarrow.compute(列式计算)
pyarrow.compute 是 Arrow 内置高性能计算库,纯列式、无Python循环、速度远超原生Python,支持过滤、聚合、数学运算、字符串处理、条件判断。
5.1 基础数学运算
python
# ========== 逐行注释 ==========
# 测试数组
arr = pa.array([1, 2, 3, 4, 5, None])
# 1. 加减乘除(逐元素运算)
add_res = pc.add(arr, 10) # 所有元素 +10
mul_res = pc.multiply(arr, 2) # 所有元素 *2
print("数组+10:", add_res)
print("数组*2:", mul_res)
# 2. 取绝对值、取反
abs_res = pc.abs(arr)
neg_res = pc.negate(arr)
print("绝对值:", abs_res)
print("取反:", neg_res)
# 3. 最值、求和、均值(聚合计算)
print("总和:", pc.sum(arr))
print("最大值:", pc.max(arr))
print("最小值:", pc.min(arr))
print("平均值:", pc.mean(arr))
print("元素个数(非空):", pc.count(arr))
5.2 条件过滤 & 布尔判断
python
# ========== 逐行注释 ==========
arr = pa.array([10, 20, 30, 40, 50])
# 1. 比较运算:> < >= <= == !=
gt_20 = pc.greater(arr, 20) # 大于20
eq_30 = pc.equal(arr, 30) # 等于30
print("大于20的布尔掩码:", gt_20)
print("等于30的布尔掩码:", eq_30)
# 2. 逻辑运算:and / or / not
mask1 = pc.greater(arr, 15)
mask2 = pc.less(arr, 45)
logic_and = pc.and_(mask1, mask2) # 同时满足两个条件
print("15 < x < 45 掩码:", logic_and)
# 3. 使用掩码过滤数据
filter_arr = pc.filter(arr, logic_and)
print("过滤后数据:", filter_arr)
# 4. Table 整表过滤
table = pa.Table.from_pydict({"num": arr, "name": ["a","b","c","d","e"]})
filtered_table = table.filter(logic_and)
print("\n过滤后的Table:")
print(filtered_table)
5.3 字符串处理函数
python
# ========== 逐行注释 ==========
str_arr = pa.array(["Hello", "PyArrow", "Python", ""])
# 1. 大小写转换
lower = pc.ascii_lower(str_arr)
upper = pc.ascii_upper(str_arr)
print("小写:", lower)
print("大写:", upper)
# 2. 字符串长度
str_len = pc.utf8_length(str_arr)
print("字符串长度:", str_len)
# 3. 字符串包含、开头、结尾
contain_py = pc.utf8_contains(str_arr, "Py")
start_h = pc.utf8_starts_with(str_arr, "H")
print("包含'Py':", contain_py)
print("以'H'开头:", start_h)
# 4. 字符串拼接
concat_str = pc.binary_join_element_wise(str_arr, pa.array(["_test"]), "")
print("字符串拼接:", concat_str)
5.4 分组聚合(Group By)
python
# ========== 逐行注释 ==========
# 构造分组测试表
group_table = pa.Table.from_pydict({
"category": ["A", "A", "B", "B", "A", "B"],
"value": [10, 20, 15, 25, 30, 35]
})
print("原始分组表:")
print(group_table)
# 1. 按 category 分组,对 value 求和、求平均
grouped = group_table.group_by("category")
agg_result = grouped.aggregate([
("value", "sum"), # 求和
("value", "mean") # 平均值
])
print("\n分组聚合结果:")
print(agg_result)
第六章 主流文件 IO(CSV / Parquet / Feather / JSON / ORC)
PyArrow 最强能力之一:高性能读写各类大数据文件格式,支持分块读取、压缩、列裁剪、流式读取。
6.1 CSV 读写
python
# ========== 逐行注释 ==========
# 测试数据
csv_table = pa.Table.from_pydict({
"id": [1,2,3,4],
"name": ["张三","李四","王五","赵六"],
"age": [20,22,19,21]
})
# 1. 写入 CSV 文件
csv_path = "test_data.csv"
pv.write_csv(csv_table, csv_path)
print(f"CSV 文件已写入: {csv_path}")
# 2. 读取 CSV(全量读取)
read_csv_table = pv.read_csv(csv_path)
print("\n读取CSV结果:")
print(read_csv_table)
# 3. 只读取指定列(列裁剪,节省内存)
csv_col_subset = pv.read_csv(csv_path, columns=["id", "name"])
print("\n只读取 id、name 列:")
print(csv_col_subset)
# 4. 分块流式读取(超大CSV专用)
print("\n分块读取CSV:")
with pv.open_csv(csv_path) as reader:
for batch in reader:
print("单个Batch:", batch)
6.2 Parquet 读写(大数据标准格式,列式压缩)
Parquet 是大数据主流存储格式,高压缩、列式索引、支持分区、Schema 持久化。
python
# ========== 逐行注释 ==========
parquet_path = "test_data.parquet"
# 1. 写入 Parquet,指定压缩算法
pq.write_table(
table=csv_table,
where=parquet_path,
compression="snappy" # 压缩:snappy/gzip/brotli
)
print(f"Parquet 文件已写入: {parquet_path}")
# 2. 全量读取 Parquet
pq_table = pq.read_table(parquet_path)
print("\n读取Parquet:")
print(pq_table)
# 3. 读取指定列 + 行过滤(列式优势:只加载需要列)
pq_sub = pq.read_table(parquet_path, columns=["name", "age"])
print("\nParquet 读取指定列:")
print(pq_sub)
# 4. 分块读取大 Parquet
print("\n分块读取Parquet:")
parquet_file = pq.ParquetFile(parquet_path)
for batch in parquet_file.iter_batches(batch_size=2):
print("Parquet Batch:", batch)
6.3 Feather 读写(Pandas/Arrow 快速交换格式)
Feather 基于 Arrow 格式,读写速度极快,适合数据分析中间文件。
python
# ========== 逐行注释 ==========
feather_path = "test_data.feather"
# 1. 写入 Feather
ft.write_feather(csv_table, feather_path)
# 2. 读取 Feather
ft_table = ft.read_feather(feather_path)
print("Feather 读取结果:")
print(ft_table)
6.4 JSON / ORC 读写
python
# ========== 逐行注释 ==========
# JSON 读写
json_path = "test_data.json"
pj.write_json(csv_table, json_path)
json_table = pj.read_json(json_path)
print("JSON 读取结果:")
print(json_table)
# ORC 读写(Hive/Spark 常用格式)
orc_path = "test_data.orc"
po.write_table(csv_table, orc_path)
orc_table = po.read_table(orc_path)
print("\nORC 读取结果:")
print(orc_table)
第七章 PyArrow ↔ Pandas / NumPy 互转
PyArrow 和 Pandas/NumPy 深度兼容,支持零拷贝转换。
python
# ========== 逐行注释 ==========
import pandas as pd
import numpy as np
# 1. Arrow Table → Pandas DataFrame
arrow_table = pa.Table.from_pydict({"a":[1,2,3], "b":["x","y","z"]})
df = arrow_table.to_pandas()
print("Arrow → Pandas:")
print(df)
# 2. Pandas DataFrame → Arrow Table
new_arrow_table = pa.Table.from_pandas(df)
print("\nPandas → Arrow:")
print(new_arrow_table)
# 3. NumPy Array → Arrow Array
np_arr = np.array([1.1, 2.2, 3.3])
arrow_arr = pa.array(np_arr)
print("\nNumPy → Arrow Array:", arrow_arr)
# 4. Arrow Array → NumPy Array
back_np = arrow_arr.to_numpy()
print("Arrow → NumPy:", back_np)
第八章 内存管理 & 零拷贝进阶
8.1 内存查看、占用统计
python
# ========== 逐行注释 ==========
test_table = pa.Table.from_pydict({
"col1": list(range(1000)),
"col2": [f"text_{i}" for i in range(1000)]
})
# 1. 查看表占用内存(字节)
mem_size = test_table.nbytes
print(f"Table 总内存: {mem_size} 字节")
# 2. 查看每一列内存
for col_name in test_table.column_names:
col = test_table[col_name]
print(f"列 {col_name} 内存: {col.nbytes} 字节")
# 3. 内存池配置(全局内存管理器)
print("默认内存池:", pa.default_memory_pool())
8.2 零拷贝原理说明
Arrow 数据在内存中是标准列式内存布局:
- Arrow ↔ NumPy / Pandas 可实现视图转换,不复制内存;
- 跨进程、跨语言(Java/C++/Go)可共享同一块内存;
- 大数据框架(Spark/Dask/Ray)均基于 Arrow 做数据交换。
第九章 实战综合案例(完整流程)
案例:CSV 清洗 → 计算 → 写入 Parquet
python
# ========== 逐行注释 ==========
# 1. 定义文件路径
source_csv = "sales.csv"
target_parquet = "sales_clean.parquet"
# 2. 模拟生成测试CSV数据
demo_data = pa.Table.from_pydict({
"sale_date": ["2026-06-01"]*5 + ["2026-06-02"]*5,
"product": ["A","B","A","C","B"]*2,
"sales_num": [10,20,None,15,25,30,12,22,18,None]
})
pv.write_csv(demo_data, source_csv)
# 3. 读取CSV
raw_table = pv.read_csv(source_csv)
print("原始数据:")
print(raw_table)
# 4. 数据清洗:填充空值 + 过滤异常数据
fill_table = raw_table.fill_null(0) # 空值填充0
mask = pc.greater(fill_table["sales_num"], 0) # 销量>0
clean_table = fill_table.filter(mask)
print("\n清洗后数据:")
print(clean_table)
# 5. 分组统计:按商品分组求和
group_result = clean_table.group_by("product").aggregate([("sales_num", "sum")])
print("\n商品销量统计:")
print(group_result)
# 6. 写入高性能Parquet文件
pq.write_table(clean_table, target_parquet, compression="snappy")
print(f"\n清洗后数据已写入 {target_parquet}")
第十章 常见问题 & 版本兼容(PyArrow 24.0.0)
- 空值报错 :Arrow 严格区分空值,创建数组时
None会自动识别,无需手动处理; - 类型转换失败 :使用
table.cast(schema)强制转换 Schema; - 大文件内存溢出 :使用
iter_batches分块读取,不要全量加载; - Pandas 转换慢:优先使用 Arrow 原生计算,减少来回转换;
- Python 3.14 兼容:PyArrow 24.0.0 完全支持 Python 3.14,无语法废弃问题。
教程总结
本教程覆盖 PyArrow 24.0.0 全核心功能:
- 环境与数据类型系统
- Array / ChunkedArray 单列数据
- Table / RecordBatch 表格数据
pyarrow.compute列式计算、过滤、分组- 全格式 IO(CSV/Parquet/Feather/JSON/ORC)
- 与 Pandas/NumPy 互转
- 内存管理 + 综合实战