Datasets documentation

与 Polars 配合使用

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v4.8.4).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

与 Polars 配合使用

本文档简要介绍了如何使用 datasets 与 Polars 配合,重点说明如何使用 Polars 函数处理数据集,以及如何在数据集与 Polars 之间进行转换。

这一点尤其有用,因为它支持快速的零拷贝操作,因为 datasets 和 Polars 底层都使用 Arrow。

数据集格式

默认情况下,数据集返回的是普通的 Python 对象:整数、浮点数、字符串、列表等。

To get Polars DataFrames or Series instead, you can set the format of the dataset to polars using Dataset.with_format():

>>> from datasets import Dataset
>>> data = {"col_0": ["a", "b", "c", "d"], "col_1": [0., 0., 1., 1.]}
>>> ds = Dataset.from_dict(data)
>>> ds = ds.with_format("polars")
>>> ds[0]       # pl.DataFrame
shape: (1, 2)
┌───────┬───────┐
│ col_0 ┆ col_1 │
│ ---   ┆ ---   │
│ str   ┆ f64   │
╞═══════╪═══════╡
│ a     ┆ 0.0   │
└───────┴───────┘
>>> ds[:2]      # pl.DataFrame
shape: (2, 2)
┌───────┬───────┐
│ col_0 ┆ col_1 │
│ ---   ┆ ---   │
│ str   ┆ f64   │
╞═══════╪═══════╡
│ a     ┆ 0.0   │
│ b     ┆ 0.0   │
└───────┴───────┘
>>> ds["data"]  # pl.Series
shape: (4,)
Series: 'col_0' [str]
[
        "a"
        "b"
        "c"
        "d"
]

对于例如使用 load_dataset(..., streaming=True) 获取的 IterableDataset 对象,此方法同样适用:

>>> ds = ds.with_format("polars")
>>> for df in ds.iter(batch_size=2):
...     print(df)
...     break
shape: (2, 2)
┌───────┬───────┐
│ col_0 ┆ col_1 │
│ ---   ┆ ---   │
│ str   ┆ f64   │
╞═══════╪═══════╡
│ a     ┆ 0.0   │
│ b     ┆ 0.0   │
└───────┴───────┘

处理数据

Polars 函数通常比常规手写 Python 函数更快,因此是优化数据处理的理想选择。您可以在 Dataset.map() 或 Dataset.filter() 中使用 Polars 函数来处理数据集:

>>> import polars as pl
>>> from datasets import Dataset
>>> data = {"col_0": ["a", "b", "c", "d"], "col_1": [0., 0., 1., 1.]}
>>> ds = Dataset.from_dict(data)
>>> ds = ds.with_format("polars")
>>> ds = ds.map(lambda df: df.with_columns(pl.col("col_1").add(1).alias("col_2")), batched=True)
>>> ds[:2]
shape: (2, 3)
┌───────┬───────┬───────┐
│ col_0 ┆ col_1 ┆ col_2 │
│ ---   ┆ ---   ┆ ---   │
│ str   ┆ f64   ┆ f64   │
╞═══════╪═══════╪═══════╡
│ a     ┆ 0.0   ┆ 1.0   │
│ b     ┆ 0.0   ┆ 1.0   │
└───────┴───────┴───────┘
>>> ds = ds.filter(lambda df: df["col_0"] == "b", batched=True)
>>> ds[0]
shape: (1, 3)
┌───────┬───────┬───────┐
│ col_0 ┆ col_1 ┆ col_2 │
│ ---   ┆ ---   ┆ ---   │
│ str   ┆ f64   ┆ f64   │
╞═══════╪═══════╪═══════╡
│ b     ┆ 0.0   ┆ 1.0   │
└───────┴───────┴───────┘

我们使用 batched=True,因为在 Polars 中按批次处理数据比逐行处理更快。也可以在 map() 中使用 batch_size= 来设置每个 df 的大小。

这对 IterableDataset.map() 和 IterableDataset.filter() 同样适用。

示例:数据提取

Polars 提供了适用于各种数据类型(如字符串、浮点数、整数等)的众多函数。您可以在此处找到完整列表。这些函数使用 Rust 编写,并对数据批次进行处理,从而实现快速的数据处理。

下面是一个示例,展示了使用 Polars 代替普通 Python 函数从 LLM 推理数据集中提取解决方案时,速度提升了 5 倍:

from datasets import load_dataset

ds = load_dataset("ServiceNow-AI/R1-Distill-SFT", "v0", split="train")

# Using a regular python function
pattern = re.compile("boxed\\{(.*)\\}")
result_ds = ds.map(lambda x: {"value_solution": m.group(1) if (m:=pattern.search(x["solution"])) else None})
# Time: 10s

# Using a Polars function
expr = pl.col("solution").str.extract("boxed\\{(.*)\\}").alias("value_solution")
result_ds = ds.with_format("polars").map(lambda df: df.with_columns(expr), batched=True)
# Time: 2s

从 Polars 导入或导出

要从 Polars 导入数据,您可以使用 Dataset.from_polars():

ds = Dataset.from_polars(df)

您可以使用 Dataset.to_polars() 将 Dataset 导出为 Polars DataFrame:

df = Dataset.to_polars(ds)
Update on GitHub