You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何使用PyArrow读取多文件Parquet数据集并添加文件来源标识列

给Parquet数据集添加来源文件标识列

当然可行!不过有个关键细节需要注意:默认情况下ParquetDataset并不会自动把文件名当作分区键——因为你的文件是直接命名为data-N.parquet,而非标准的分区目录结构(比如source_file=data-1.parquet/这种形式)。不过我们有两种实用的方法来实现你的需求:

方法一:手动遍历文件读取(直观易控)

这种方法适合文件数量不算特别多的场景,直接逐个读取文件并添加来源列,最后合并成总DataFrame:

import glob
import pandas as pd
import pyarrow.parquet as pq
import os

dfs_list = []
# 遍历所有匹配的Parquet文件
for file_path in glob.glob("data-**.parquet"):
    # 读取单个文件为DataFrame
    single_df = pq.read_table(file_path).to_pandas()
    # 可选择只保留文件名而非完整路径
    single_df["source_file"] = os.path.basename(file_path)
    dfs_list.append(single_df)

# 合并所有DataFrame,重置索引
final_dataframe = pd.concat(dfs_list, ignore_index=True)

这个方法的优势是逻辑清晰,你可以灵活调整文件名的存储格式,比如只保留文件名或截取特定部分。

方法二:利用ParquetDataset的分区信息(高效并行)

如果你的数据集很大,想要保留ParquetDataset的并行读取优势,可以通过提取分区索引来映射文件名:

import glob
import pandas as pd
import pyarrow.parquet as pq
import pyarrow

files = glob.glob("data-**.parquet")
# 读取Parquet数据集
ds = pq.ParquetDataset(
    files,
    metadata_nthreads=64,
).read_table(use_threads=True)

# 创建分区索引到文件名的映射(每个文件对应一个分区)
partition_file_map = {idx: file for idx, file in enumerate(files)}
# 生成对应每条数据的来源文件数组
source_file_array = pyarrow.array(
    [partition_file_map[part_idx] for part_idx in ds.partition_indices],
    type=pyarrow.string()
)
# 添加新列到数据集
ds_with_source = ds.add_column("source_file", source_file_array)

# 转换为Pandas DataFrame
final_dataframe = ds_with_source.to_pandas()

这里的核心是ds.partition_indices——它会为每条数据标记所属的分区索引(也就是对应的文件顺序),通过映射关系就能把文件名关联到每条数据上,完美保留了ParquetDataset的高效读取特性。

两种方法都能实现你的需求,你可以根据数据规模和个人习惯选择~

内容的提问来源于stack exchange,提问作者Cedric H.

火山引擎 最新活动