Pandas无法读取在PySp中创建的拼花文件

2024-03-29 13:59:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用以下方法从Spark数据帧中编写一个拼花文件:

df.write.parquet("path/myfile.parquet", mode = "overwrite", compression="gzip")

这将创建一个包含多个文件的文件夹。

当我试图将其读入pandas时,根据使用的解析器,会出现以下错误:

import pandas as pd
df = pd.read_parquet("path/myfile.parquet", engine="pyarrow")

箭头:

File "pyarrow\error.pxi", line 83, in pyarrow.lib.check_status

ArrowIOError: Invalid parquet file. Corrupt footer.

快速拼花:

File "C:\Program Files\Anaconda3\lib\site-packages\fastparquet\util.py", line 38, in default_open return open(f, mode)

PermissionError: [Errno 13] Permission denied: 'path/myfile.parquet'

我使用以下版本:

  • 火花2.4.0
  • 熊猫0.23.4
  • 皮亚罗0.10.0
  • 快速拼花0.2.1

我尝试了gzip和快速压缩。两者都不起作用。当然,我确保文件位于Python有读/写权限的位置。

如果有人能重现这个错误,这已经有帮助了。


Tags: 文件pathinpandasdfmode错误line
2条回答

由于这似乎仍然是一个问题,即使是较新的pandas版本,我编写了一些函数来规避这一点,作为一个更大的pyspark helpers库的一部分:

import pandas as pd
import datetime

def read_parquet_folder_as_pandas(path, verbosity=1):
  files = [f for f in os.listdir(path) if f.endswith("parquet")]

  if verbosity > 0:
    print("{} parquet files found. Beginning reading...".format(len(files)), end="")
    start = datetime.datetime.now()

  df_list = [pd.read_parquet(os.path.join(path, f)) for f in files]
  df = pd.concat(df_list, ignore_index=True)

  if verbosity > 0:
    end = datetime.datetime.now()
    print(" Finished. Took {}".format(end-start))
  return df


def read_parquet_as_pandas(path, verbosity=1):
  """Workaround for pandas not being able to read folder-style parquet files.
  """
  if os.path.isdir(path):
    if verbosity>1: print("Parquet file is actually folder.")
    return read_parquet_folder_as_pandas(path, verbosity)
  else:
    return pd.read_parquet(path)

这假设拼花“文件”中的相关文件实际上是一个文件夹,以“.parquet”结尾。这适用于数据块导出的拼花文件,也可能适用于其他人(未经测试,对评论中的反馈感到满意)。

如果事先不知道函数read_parquet_as_pandas()是否是文件夹,则可以使用该函数。

问题是Spark由于文件的分布式特性而对其进行分区(每个执行器在接收文件名的目录中写入一个文件)。这不是Pandas所支持的,它需要一个文件,而不是一个路径。

你可以用不同的方式来规避这个问题:

  • 使用替代实用程序(如pyarrow.parquet.ParquetDataset)读取文件,然后将其转换为Pandas(我没有测试此代码)。

    arrow_df = pyarrow.parquet.ParquetDataset('path/myfile.parquet')
    pandas_df = arrow_df.to_pandas()
    
  • 另一种方法是分别读取单独的片段,然后将它们连接起来,正如这个答案所建议的那样:Read multiple parquet files in a folder and write to single csv file using python

相关问题 更多 >