演示如何将Pandas数据框追加到现有的.parquet文件中。
注意:其他答案无法将内容追加到现有的.parquet文件中,但此方法可以;请参见结尾处的讨论。
在Windows和Linux上测试了Python v3.9。
使用pip安装PyArrow:
pip install pyarrow==6.0.1
或者Anaconda/ Miniconda:
conda install -c conda-forge pyarrow=6.0.1 -y
演示代码:
# Q. Demo?
# A. Demo of appending to an existing .parquet file by memory mapping the original file, appending the new dataframe, then writing the new file out.
import os
import numpy as np
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
filepath = "parquet_append.parquet"
方法1/2
简单方法:使用pandas将原始的.parquet文件读入,追加后,再将整个文件写回。
df = pd.DataFrame({"x": [1.,2.,np.nan], "y": ["a","b","c"]})
df.to_parquet(filepath)
df = pd.read_parquet(filepath)
df2 = pd.DataFrame({"x": [3.,4.,np.nan], "y": ["d","e","f"]})
df3 = pd.concat([df, df2])
df3.to_parquet(filepath)
df_copy = pd.read_parquet(filepath)
print(df_copy)
第二种方法:更为复杂但速度更快
使用原生PyArrow调用,内存映射原始文件,将新的数据框追加到其中,然后将新文件写出。
df = pd.DataFrame({"x": [1.,2.,np.nan], "y": ["a","b","c"]})
table = pa.Table.from_pandas(df)
pq.write_table(table, where=filepath)
def parquet_append(filepath:Path or str, df: pd.DataFrame) -> None:
"""
Append to dataframe to existing .parquet file. Reads original .parquet file in, appends new dataframe, writes new .parquet file out.
:param filepath: Filepath for parquet file.
:param df: Pandas dataframe to append. Must be same schema as original.
"""
table_original_file = pq.read_table(source=filepath, pre_buffer=False, use_threads=True, memory_map=True)
table_to_append = pa.Table.from_pandas(df)
table_to_append = table_to_append.cast(table_original_file.schema)
handle = pq.ParquetWriter(filepath, table_original_file.schema)
handle.write_table(table_original_file)
handle.write_table(table_to_append)
handle.close()
df = pd.DataFrame({"x": [3.,4.,np.nan], "y": ["d","e","f"]})
parquet_append(filepath, df)
df_copy = pd.read_parquet(filepath)
print(df_copy)
讨论
@Ibraheem Ibraheem 和 @yardstick17 的答案不能用于追加到现有的 .parquet 文件中:
- 限制 1:一旦调用了
.close()
,文件就无法再追加。一旦页脚被写入,一切都已经定型;
- 限制 2:在调用
.close()
之前,任何其他程序都无法读取 .parquet 文件(因为二进制页脚缺失会抛出异常)。
综合这些限制,意味着它们不能用于追加到现有的 .parquet 文件中,它们只能用于以块的形式编写 .parquet 文件。上述技术消除了这些限制,但代价是要将整个文件重写以追加到结尾。经过广泛的研究,我相信使用现有的 PyArrow 库(截至 v6.0.1),不可能追加到现有的 .parquet 文件中。
可以将此方法修改为将文件夹中的多个 .parquet 文件合并成单个 .parquet 文件。
可以执行有效的 upsert 操作:pq.read_table() 具有对列和行进行筛选的过滤器,因此如果在加载时从原始表格中筛选出了行,则新表格中的行会有效地替换旧表格中的行。这对于时间序列数据更有用。