Python中读写Parquet文件的方法

Apache Parquet 文件是数据科学家和任何使用 Hadoop 生态系统的人所使用的流行列式存储格式。它的开发在压缩和编码方面非常高效。

您可以使用pyarrow 包通过 Python 读取和写入 Parquet 文件。

现在让我们来了解一下它是如何工作的!

安装 pyarrow
第一步是确保您拥有所需的一切。除了 Python 编程语言之外,您还需要pyarrow和pandas包。您将使用 pandas,因为它是另一个使用列作为数据格式的 Python 包,并且可以很好地与 Parquet 文件配合使用。

您可以使用 pip 安装这两个软件包。打开终端并运行以下命令:

python -m pip install pyarrow pandas

如果您使用 Anaconda,则需要使用此命令安装 pyarrow。
conda install -c conda-forge pyarrow

Anaconda 应该已经包含 pandas,但如果没有,您可以使用上面相同的命令,将 pyarrow 替换为 pandas。

现在您已经安装了 pyarrow 和 pandas,您可以使用它来读取和写入 Parquet 文件!

使用 Python 编写 Parquet 文件
使用 Python 编写 Parquet 文件非常简单。将 pandas DataFrame 转换为 Parquet 文件的代码大约有十行。

打开您最喜欢的 Python IDE 或文本编辑器并创建一个新文件。您可以将其命名为类似的名称parquet_file_writer.py或使用其他描述性名称。然后输入以下代码:


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


def write_parquet(df: pd.DataFrame, filename: str) -> None:
    table = pa.Table.from_pandas(df)
    pq.write_table(table, filename)
    

if __name__ == "__main__":
    data = {
"Languages": ["Python", "Ruby", "C++"],
           
"Users": [10000, 5000, 8000],
           
"Dynamic": [True, True, False],
            }
    df = pd.DataFrame(data=data, index=list(range(1, 4)))
    write_parquet(df,
"languages.parquet")


对于此示例,您有三个导入:

  • 一个用于pandas,这样您就可以创建一个DataFrame
  • 一个用于pyarrow, 创建一个特殊pyarrow.Table对象
  • 一种用于pyarrow.parquet将表对象转换为 Parquet 文件

write_parquet   ()函数接受 pandas DataFrame 和保存 Parquet 文件的文件名或路径。然后,将 DataFrame 转换为 pyarrow Table 对象,然后使用该write_table()方法将其转换为 Parquet 文件,并将其写入磁盘。

现在您可以阅读刚刚创建的文件了!

使用 Python 读取 Parquet 文件
读取您之前使用 Python 创建的 Parquet 文件更加容易。您将需要大约一半的代码行!

parquet_file_reader.py如果您愿意,您可以将以下代码放入一个名为类似以下内容的新文件中:

import pyarrow.parquet as pq

def read_parquet(filename: str) -> None:
    table = pq.read_table(filename)
    df = table.to_pandas()
    print(df)

if __name__ == "__main__":    
    read_parquet(
"languages.parquet")


在此示例中,您将 Parquet 文件读取为 pyarrow Table 格式,然后使用 Table 的to_pandas()方法将其转换为 pandas DataFrame。

当你打印出DataFrame的内容时,你将看到以下内容:

  Languages  Users  Dynamic
1    Python  10000     True
2      Ruby   5000     True
3       C++   8000    False


从上面的输出中您可以看到 DataFrame 包含您保存的所有数据。

使用 Parquet 文件的优点之一是您可以仅读取文件的一部分而不是整个文件。例如,您可以只读取某些列,而不是整个文件!

以下是其工作原理的示例:

import pyarrow.parquet as pq

def read_columns(filename: str, columns: list[str]) -> None:
    table = pq.read_table(filename, columns=columns)
    print(table)

if __name__ == "__main__":
    read_columns(
"languages.parquet", columns=["Languages", "Users"])

要仅读取 Parquet 文件中的“语言”和“用户”列,请传入仅包含这些列名称的列表。然后,当您调用 read_table()时,您传入要读取的列。

这是运行此代码时的输出:

pyarrow.Table
Languages: string
Users: int64
----
Languages: [["Python","Ruby","C++"]]
Users: [[10000,5000,8000]]


这会输出 pyarrow Table 格式,它与 pandas DataFrame 略有不同。它告诉您有关不同列的信息;例如,Languages 是字符串,Users 是 int64 类型。

如果您更喜欢仅使用 pandas DataFrames,pyarrow 包也允许这样做。只要您知道 Parquet 文件包含 pandas DataFrame,您就可以使用 read_pandas()而不是 read_table()。

这是一个代码示例:

pyarrow.Table
Languages: string
Users: int64
----
Languages: [["Python","Ruby","C++"]]
Users: [[10000,5000,8000]]


当您运行此示例时,输出是一个 DataFrame,其中仅包含您要求的列:

  Languages  Users
1    Python  10000
2      Ruby   5000
3       C++   8000


使用 read_pandas() 和 to_pandas() 方法的优点之一是它们将在 DataFrame 中维护任何其他索引列数据,而 pyarrow Table 可能不会。

读取 Parquet 文件元数据
您还可以使用 Python 从 Parquet 文件获取元数据。当您需要检查不熟悉的 Parquet 文件以查看它包含什么类型的数据时,获取元数据会很有用。

下面是一个小代码片段,它将读取 Parquet 文件的元数据和架构:

import pyarrow.parquet as pq

def read_metadata(filename: str) -> None:
    parquet_file = pq.ParquetFile(filename)
    metadata =  parquet_file.metadata
    print(metadata)
    print(f"Parquet file: {filename} Schema")
    print(parquet_file.schema)

if __name__ ==
"__main__":
    read_metadata(
"languages.parquet")


有两种方法可以获取 Parquet 文件的元数据:

  • 使用pq.ParquetFile读取文件,然后访问 元数据属性
  • 使用 pr.read_metadata(filename)代替

前一种方法的好处是您还可以访问 ParquetFile对象的schema属性。

当您运行此代码时,您将看到以下输出:

<pyarrow._parquet.FileMetaData object at 0x000002312C1355D0>
  created_by: parquet-cpp-arrow version 15.0.2
  num_columns: 4
  num_rows: 3
  num_row_groups: 1
  format_version: 2.6
  serialized_size: 2682
Parquet file: languages.parquet Schema
<pyarrow._parquet.ParquetSchema object at 0x000002312BBFDF00>
required group field_id=-1 schema {
  optional binary field_id=-1 Languages (String);
  optional int64 field_id=-1 Users;
  optional boolean field_id=-1 Dynamic;
  optional int64 field_id=-1 __index_level_0__;
}


好的!您可以阅读上面的输出来了解数据的行数和列数以及数据的大小。该架构告诉您字段类型是什么。

总结
Parquet 文件在大数据和数据科学相关领域变得越来越流行。 Python 的 pyarrow 包使 Parquet 文件的处理变得简单。您应该花一些时间尝试本教程中的代码,并将其用于您自己的一些 Parquet 文件。