如何使用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.




