Datasets documentation
الاستخدام مع Polars
الاستخدام مع Polars
هذا المستند مقدمة سريعة لاستخدام datasets مع Polars، مع تركيز خاص على كيفية معالجة مجموعات البيانات باستخدام دوال Polars، وكيفية تحويل مجموعة بيانات إلى Polars أو من Polars.
يُعدّ هذا مفيدًا بشكل خاص لأنه يتيح عمليات سريعة بدون نسخ، نظرًا لأن كلًا من datasets وPolars يستخدمان Arrow في الخلفية.
تنسيق مجموعة البيانات
بشكل افتراضي، تُرجع مجموعات البيانات كائنات بايثون العادية: أعداد صحيحة، وأعداد عشرية، ونصوص، وقوائم، وما إلى ذلك.
للحصول على إطارات بيانات Polars أو سلاسل Series بدلاً من ذلك، يمكنك تعيين صيغة مجموعة البيانات إلى polars باستخدام 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"
]يعمل هذا أيضًا مع كائنات IterableDataset التي يتم الحصول عليها، على سبيل المثال، باستخدام load_dataset(..., streaming=True):
>>> 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 المكتوبة يدويًا، ولذلك تُعد خيارًا جيدًا لتحسين معالجة البيانات. يمكنك استخدام دوال Polars لمعالجة مجموعة بيانات في Dataset.map() أو Dataset.filter():
>>> 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 أسرع من المعالجة صفًا بصف. كما يمكن استخدام batch_size= في map() لتحديد حجم كل df.
يعمل هذا أيضًا مع IterableDataset.map() و IterableDataset.filter().
مثال: استخراج البيانات
يتوفر في Polars العديد من الدوال لجميع أنواع البيانات: النصوص، والأعداد العشرية، والأعداد الصحيحة، وغيرها. يمكنك العثور على القائمة الكاملة هنا. كُتبت هذه الدوال بلغة Rust وتعمل على دفعات من البيانات مما يتيح معالجة البيانات بسرعة.
فيما يلي مثال يُظهر تسريعًا بمقدار 5 أضعاف باستخدام Polars بدلاً من دالة Python عادية لاستخراج الحلول من مجموعة بيانات استدلال نموذج LLM:
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() لتصدير مجموعة بيانات إلى إطار بيانات Polars:
df = Dataset.to_polars(ds)