Polars في Rust: دليل شامل مع أمثلة عملية

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مكتبة Polars في Rust: دليل شامل

Polars هي مكتبة عالية الأداء للتعامل مع البيانات بتنسيق DataFrame، مكتوبة بلغة Rust. توفر واجهة برمجة تطبيقات مألوفة لمستخدمي pandas، ولكنها تتفوق عليه بشكل كبير في السرعة وكفاءة استهلاك الذاكرة. على عكس pandas الذي غالبًا ما يصطدم بقيود التنفيذ أحادي الخيط واستهلاك الذاكرة العشوائية، صُممت Polars من البداية للعمل في وضع متعدد الخيوط وتستخدم الحسابات البطيئة (lazy API) لتحسين الاستعلامات.

الهدف الرئيسي لـ Polars هو توفير أداة لمعالجة كميات كبيرة من البيانات (من مئات الميغابايت إلى عدة تيرابايت) على عقدة واحدة، دون الحاجة إلى أنظمة موزعة مثل Spark. يتم تحقيق ذلك من خلال العمل الفعال مع الذاكرة (النسخ الصفري، استخدام Apache Arrow كخلفية)، وتوجيه العمليات، والتوازي التلقائي. بالنسبة لمطوري Rust، فإن Polars ليست مجرد غلاف لمكتبة Python، بل هي مكتبة أصلية تستخدم بالكامل إمكانيات اللغة: أمان الذاكرة، نظام الأنواع، والأداء.

تقدم المكتبة واجهتي برمجة تطبيقات: Eager (حسابات فورية) و Lazy (حسابات بطيئة). واجهة Eager مناسبة للعمل التفاعلي ومجموعات البيانات الصغيرة، حيث تحتاج إلى رؤية النتيجة فورًا. تتيح واجهة Lazy بناء خطة استعلام، يتم تحسينها وتنفيذها في مسار واحد، وهو أمر بالغ الأهمية للتحويلات المعقدة والبيانات الضخمة. تدعم Polars أيضًا العمل مع CSV و Parquet و JSON و IPC (Arrow) وقواعد البيانات عبر SQL.

التثبيت

لإضافة Polars إلى مشروع Rust، أضف التبعية إلى ملف Cargo.toml:

[dependencies]
polars = "0.44.0"  # تحقق من أحدث إصدار على crates.io

إذا كنت بحاجة إلى ميزات إضافية (مثل دعم التعبيرات النمطية للنصوص، العمل مع التواريخ، أو التكامل مع SQL)، استخدم الميزات:

[dependencies]
polars = { version = "0.44.0", features = ["lazy", "strings", "dtype-date", "dtype-datetime", "sql", "parquet", "csv"] }

الميزات الرئيسية:

  • lazy — واجهة الحسابات البطيئة (ضرورية للعمل الجاد)
  • strings — دوال للتعامل مع النصوص (contains, replace, extract)
  • dtype-date, dtype-datetime — دعم أنواع التواريخ
  • sql — واجهة SQL
  • parquet — قراءة/كتابة Parquet
  • csv — قراءة/كتابة CSV
  • is_in, rank, moment — دوال إضافية

بعد إضافة التبعية، نفذ الأمر:

cargo build

بداية سريعة

مثال عملي بسيط لإنشاء DataFrame وتنفيذ استعلام:

use polars::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // إنشاء DataFrame من المتجهات
    let df = df! [
        "name" => &["أحمد", "سارة", "خالد"],
        "age" => &[25, 30, 35],
        "salary" => &[50000, 60000, 70000]
    ]?;

    println!("البيانات الأصلية:\n{:?}", df);

    // تصفية: من هم أكبر من 28 سنة
    let filtered = df.clone().lazy()
        .filter(col("age").gt(lit(28)))
        .collect()?;

    println!("المصفاة (العمر > 28):\n{:?}", filtered);

    // تجميع: متوسط الراتب
    let avg_salary = df.clone().lazy()
        .select([col("salary").mean().alias("متوسط_الراتب")])
        .collect()?;

    println!("متوسط الراتب:\n{:?}", avg_salary);

    Ok(())
}

يقوم هذا الكود بإنشاء جدول بثلاثة أعمدة، وتصفية الصفوف حسب العمر، وحساب متوسط الراتب. لاحظ استخدام lazy() — حتى للعمليات البسيطة، يُنصح باستخدامها للاستفادة من تحسينات الأداء.

توصيات