跳到内容

Hive

扫描 Hive 分区数据

Polars 支持扫描 Hive 分区的 Parquet 和 IPC 数据集,未来计划支持其他格式。

如果 scan_parquet 接收单个目录路径,则 Hive 分区解析默认启用;否则默认禁用。可以使用 hive_partitioning 参数进行显式配置。

扫描 Hive 目录

本示例使用以下目录结构:

┌───────────────────────────────────────────────────────┐
│ File path                                             │
╞═══════════════════════════════════════════════════════╡
│ docs/assets/data/hive/year=2023/month=11/data.parquet │
│ docs/assets/data/hive/year=2023/month=12/data.parquet │
│ docs/assets/data/hive/year=2024/month=01/data.parquet │
│ docs/assets/data/hive/year=2024/month=02/data.parquet │
└───────────────────────────────────────────────────────┘

只需将目录传递给 scan_parquet,所有文件都将加载,并将路径中的 Hive 分区包含在输出中。

scan_parquet

import polars as pl

df = pl.scan_parquet("docs/assets/data/hive/").collect()

with pl.Config(tbl_rows=99):
    print(df)

shape: (11, 3)
┌─────┬──────┬───────┐
│ x   ┆ year ┆ month │
│ --- ┆ ---  ┆ ---   │
│ i64 ┆ i64  ┆ i64   │
╞═════╪══════╪═══════╡
│ 1   ┆ 2023 ┆ 11    │
│ 2   ┆ 2023 ┆ 11    │
│ 3   ┆ 2023 ┆ 12    │
│ 4   ┆ 2023 ┆ 12    │
│ 5   ┆ 2023 ┆ 12    │
│ 6   ┆ 2024 ┆ 1     │
│ 7   ┆ 2024 ┆ 1     │
│ 8   ┆ 2024 ┆ 2     │
│ 9   ┆ 2024 ┆ 2     │
│ 10  ┆ 2024 ┆ 2     │
│ 11  ┆ 2024 ┆ 2     │
└─────┴──────┴───────┘

处理混合文件

如果目录中存在不同扩展名的文件,将目录传递给 scan_parquet 可能无法工作。

本示例使用以下目录结构:

┌─────────────────────────────────────────────────────────────┐
│ File path                                                   │
╞═════════════════════════════════════════════════════════════╡
│ docs/assets/data/hive_mixed/description.txt                 │
│ docs/assets/data/hive_mixed/year=2023/month=11/data.parquet │
│ docs/assets/data/hive_mixed/year=2023/month=12/data.parquet │
│ docs/assets/data/hive_mixed/year=2024/month=01/data.parquet │
│ docs/assets/data/hive_mixed/year=2024/month=02/data.parquet │
└─────────────────────────────────────────────────────────────┘

scan_parquet

from pathlib import Path

try:
    pl.scan_parquet("docs/assets/data/hive_mixed/").collect()
except Exception as e:
    print(e)

上述操作失败,因为 description.txt 不是有效的 Parquet 文件。

directory contained paths with different file extensions: \
                first path: docs/assets/data/hive_mixed/description.txt, second path: docs/assets/data/hive_mixed/year=2023/month=11/data.parquet. Please use a glob pattern to explicitly specify \
                which files to read (e.g. "dir/**/*", "dir/**/*.parquet")

在这种情况下,可以使用 glob 模式更具体地指定要加载的文件。请注意,hive_partitioning 必须显式设置为 True

scan_parquet

df = pl.scan_parquet(
    # Glob to match all files ending in `.parquet`
    "docs/assets/data/hive_mixed/**/*.parquet",
    hive_partitioning=True,
).collect()

with pl.Config(tbl_rows=99):
    print(df)

shape: (11, 3)
┌─────┬──────┬───────┐
│ x   ┆ year ┆ month │
│ --- ┆ ---  ┆ ---   │
│ i64 ┆ i64  ┆ i64   │
╞═════╪══════╪═══════╡
│ 1   ┆ 2023 ┆ 11    │
│ 2   ┆ 2023 ┆ 11    │
│ 3   ┆ 2023 ┆ 12    │
│ 4   ┆ 2023 ┆ 12    │
│ 5   ┆ 2023 ┆ 12    │
│ 6   ┆ 2024 ┆ 1     │
│ 7   ┆ 2024 ┆ 1     │
│ 8   ┆ 2024 ┆ 2     │
│ 9   ┆ 2024 ┆ 2     │
│ 10  ┆ 2024 ┆ 2     │
│ 11  ┆ 2024 ┆ 2     │
└─────┴──────┴───────┘

扫描包含 Hive 分区的文件路径

对于文件路径,hive_partitioning 默认不启用。

scan_parquet

df = pl.scan_parquet(
    [
        "docs/assets/data/hive/year=2024/month=01/data.parquet",
        "docs/assets/data/hive/year=2024/month=02/data.parquet",
    ],
).collect()

print(df)

shape: (6, 1)
┌─────┐
│ x   │
│ --- │
│ i64 │
╞═════╡
│ 6   │
│ 7   │
│ 8   │
│ 9   │
│ 10  │
│ 11  │
└─────┘

传入 hive_partitioning=True 以启用 Hive 分区解析。

scan_parquet

df = pl.scan_parquet(
    [
        "docs/assets/data/hive/year=2024/month=01/data.parquet",
        "docs/assets/data/hive/year=2024/month=02/data.parquet",
    ],
    hive_partitioning=True,
).collect()

print(df)

shape: (6, 3)
┌─────┬──────┬───────┐
│ x   ┆ year ┆ month │
│ --- ┆ ---  ┆ ---   │
│ i64 ┆ i64  ┆ i64   │
╞═════╪══════╪═══════╡
│ 6   ┆ 2024 ┆ 1     │
│ 7   ┆ 2024 ┆ 1     │
│ 8   ┆ 2024 ┆ 2     │
│ 9   ┆ 2024 ┆ 2     │
│ 10  ┆ 2024 ┆ 2     │
│ 11  ┆ 2024 ┆ 2     │
└─────┴──────┴───────┘

写入 Hive 分区数据

注意:以下功能被视为 不稳定,可能会有更改。

Polars 支持写入 Hive 分区的 Parquet 数据集,未来计划支持其他格式。

示例

本示例使用以下 DataFrame:

df = pl.DataFrame({"a": [1, 1, 2, 2, 3], "b": [1, 1, 1, 2, 2], "c": 1})
print(df)
shape: (5, 3)
┌─────┬─────┬─────┐
│ a   ┆ b   ┆ c   │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i32 │
╞═════╪═════╪═════╡
│ 1   ┆ 1   ┆ 1   │
│ 1   ┆ 1   ┆ 1   │
│ 2   ┆ 1   ┆ 1   │
│ 2   ┆ 2   ┆ 1   │
│ 3   ┆ 2   ┆ 1   │
└─────┴─────┴─────┘

我们将其写入一个 Hive 分区的 Parquet 数据集,按列 ab 分区。

write_parquet

df.write_parquet("docs/assets/data/hive_write/", partition_by=["a", "b"])

输出是一个 Hive 分区的 Parquet 数据集,具有以下路径:

┌───────────────────────────────────────────────┐
│ File path                                     │
╞═══════════════════════════════════════════════╡
│ docs/assets/data/hive_write/a=1/b=1/0.parquet │
│ docs/assets/data/hive_write/a=2/b=1/0.parquet │
│ docs/assets/data/hive_write/a=2/b=2/0.parquet │
│ docs/assets/data/hive_write/a=3/b=2/0.parquet │
└───────────────────────────────────────────────┘