باي سبارك: كيفية استخدام fillna() مع عمود آخر

دليل أكاديمي شامل يوضح كيفية استبدال القيم المفقودة في باي سبارك باستخدام قيم من عمود آخر بالاعتماد على دالتي coalesce وwhen-otherwise البديلتين لدالة fillna.

Mohammed looti أكاديمي وباحث متخصص في علم النفس
تاريخ النشر
تمت المراجعة العلمية · د. مروة عبد العظيم · 28 أكتوبر، 2026
مراجعة وتدقيق علمي معتمد تاريخ التدقيق: 28 أكتوبر، 2026
د. مروة عبد العظيم دكتوراه في علم النفس
عضو هيئة التدريس • جامعة كربلاء
معايير التدقيق والاعتماد السريري

يخضع هذا المحتوى لمعايير ضبط الجودة والتدقيق العلمي والأكاديمي الصارمة في شبكة علم النفس العربي، لضمان صحة المعلومات ودقتها السريرية ومطابقتها لأحدث الأدلة والبراهين الصادرة عن الجمعيات النفسية والطبية المعتمدة (APA / WHO).

تُعد معالجة البيانات غير المكتملة إحدى الركائز الأساسية في هندسة البيانات الحديثة وتعلم الآلة التطبيقي، لاسيما عند التعامل مع مجموعات بيانية ضخمة تتطلب بيئات معالجة موزعة مثل أباتشي سبارك (Apache Spark). وفي إطار العمل البرمجي لمكتبة باي سبارك (PySpark)، يواجه مهندسو وعلماء البيانات تحدياً تقنياً شائعاً ينشأ عند محاولة ملء القيم الفارغة في عمود معين استناداً إلى قيم عمود بديل داخل نفس إطار البيانات؛ حيث يكتشف المطور أن الدالة التقليدية المخصصة لملء الفراغات، وهي دالة fillna() أو ما يقابلها na.fill()، تفرض قيوداً معمارية صارمة تمنع تمرير مراجع الأعمدة كمدخلات بديلة، مما يقود مباشرة إلى استثناءات برمجية غير متوقعة للمطورين المعتادين على مرونة مكتبة بانداس (Pandas).

تكمن جذور هذا التحدي في التباين الجوهري بين بنية الحوسبة المركزية في الذاكرة المحلية وبنية الحوسبة الموزعة غير القابلة للتغيير (Immutable Distributed Computing). فمحرك سبارك يعتمد على مخططات تنفيذ تعبيرية ومؤجلة (Lazy Evaluation) تُبنى وتُدار عبر مُحسِّن الاستعلامات التحفيزي (Catalyst Optimizer)، مما يجعل مفهوم تعديل القيم موضعياً أمراً غير متوافق مع مبادئ التوازي وتجنب خلط البيانات المكلف بين العقد الحوسبية. ومن ثم، فإن محاولة استخدام دوال الاستبدال الكلاسيكية لتعويض القيم المفقودة بين الأعمدة تتطلب فهماً عميقاً لآليات التحويل التعبيري (Expression-based Transformations) بدلاً من استدعاء الدوال المصممة لمعالجة القيم العددية أو النصية الثابتة فقط.

يهدف هذا المقال الأكاديمي الشامل إلى استعراض المعضلة التقنية لتحييد القيم المفقودة باستخدام أعمدة بديلة في بيئة باي سبارك، متناولاً الأسس النظرية الإحصائية لفقدان البيانات، ومفككاً القيود البنيوية لدالة fillna()، ومستعرضاً الحلول المعيارية المعتمدة على الدوال التعبيرية البديلة مثل coalesce() والتراكيب الشرطية when().otherwise(). كما يتعمق المقال في تحليل خطط التنفيذ المادية، وإدارة تكافؤ الأنواع، ومراعاة الأداء في نظم المعالجة المتوازية، وصولاً إلى صياغة خطوط أنابيب إنتاجية تتسم بالمتانة وقابلية التدقيق الإحصائي والحوكمة البيانية الصارمة.

1. الأسس النظرية لمعالجة القيم المفقودة في بيئات البيانات الضخمة

1.1 طبيعة البيانات المفقودة وتأثيرها على النمذجة الإحصائية

تنطلق دراسة البيانات المفقودة من تصنيف الآليات المولدة لغياب البيانات، وهو المفهوم المنهجي الذي أرسى قواعده الإحصائي دونالد روبين عام 1976. تُصنف البيانات المفقودة إلى ثلاثة أنماط رئيسية تحدد المسار الرياضي والتقني الواجب اتباعه: الفقد التام عشوائياً (Missing Completely at Random – MCAR)، حيث لا يرتبط احتمال فقدان القيمة بالمتغير نفسه أو بأي متغيرات أخرى مرصودة داخل النموذج؛ والفقد العشوائي (Missing at Random – MAR)، وفيه يعتمد احتمال غياب البيانات على متغيرات أخرى ملحوظة ومقاسة دون أن يرتبط بالقيمة المفقودة ذاتها؛ وأخيراً الفقد غير العشوائي (Missing Not at Random – MNAR)، حيث تكون آلية الفقدان ناتجة عن القيمة غير المرصودة بشكل مباشر، كما يحدث عند امتناع أصحاب الدخول المرتفعة عن الإفصاح عن مستويات ثرواتهم في الاستبيانات الاستقصائية.

إن وجود القيم الخالية (Null Values) في المصفوفات البيانية لا يقتصر أثره على النقص الحجمي للمعلومات، بل يمتد ليزعزع البنية الرياضية للتوزيعات الاحتمالية للمتغيرات، مما ينتج عنه انحياز منهجي (Systematic Bias) في التقديرات الإحصائية، وتقليص حجم العينات الفعالة، وتشويش مصفوفات التباين والتباين المشترك (Covariance Matrices). هذا التشوه يقود بالتبعية إلى تقويض صلاحية الاختبارات الفرضية والاستدلالات الإحصائية، حيث تميل النماذج التي تتجاهل بنية الفقدان إلى تضخيم الخطأ المعياري وتقليل القوة الاختبارية للنماذج الرياضية المبنية عليها.

تتعاظم هذه التحديات الإحصائية بصورة بالغة عند الانتقال إلى بيئات الحوسبة الموزعة ونظم معالجة الرتل والبيانات المتدفقة (Streaming Data). ففي هذه البيئات، لا تتوزع البيانات عبر معالج أحادي الذاكرة، بل تتشتت عبر مئات العقد الحسابية في هيئة أجزاء مجزأة (Partitions). يؤدي غياب التجانس في كثافة القيم المفقودة بين الأجزاء إلى تفاوت أوقات المعالجة وحدوث اختناقات في الأداء، فضلاً عن تعقيد خوارزميات الاستيفاء الإحصائي الموزع (Distributed Imputation Algorithms)، التي تتطلب تواصلاً شبكياً كثيفاً بين العقد لحساب المتوسطات الحسابية أو المقاييس المعتمدة على الانحدار الخطي أو اللوجستي عبر كامل فضاء البيانات.

1.2 بنية تمثيل القيم الفارغة في محرك أباتشي سبارك

يتبنى محرك أباتشي سبارك فصلاً دلالياً دقيقاً بين المفاهيم المتباينة لغياب البيانات في أطر البيانات (DataFrames). يتمثل المفهوم الأول في القيمة المنطقية الخالية (SQL NULL)، والتي تشير إلى انعدام وجود القيمة أو كونها غير معروفة في السياق العلائقي، وتتوافق بنيوياً مع كائن None في لغة بايثون. أما المفهوم الثاني فهو الرمز الحسابي (NaN – Not a Number)، المعرّف وفق معيار الحوسبة العائمة IEEE 754، والذي يمثل نتيجة لعملية حسابية غير معرفة رياضياً، مثل قسمة الصفر على الصفر أو استخراج الجذر التربيعي لعدد سالب دون الانتقال إلى الأعداد المركبة. ويتعامل محرك سبارك مع كلتا الحالتين بآليات متمايزة جوهرياً داخل شجرة التعبيرات ومحرك التحسين.

على مستوى إدارة الذاكرة المنخفضة، يُوظف محرك سبارك التحفيزي (Catalyst Optimizer) ومشروع تونغستن (Project Tungsten) ما يُعرف بخرائط البتات الصفرية (Null Bitmaps) لتخزين وتتبع القيم الفارغة بكفاءة استثنائية. فبدلاً من تخصيص مؤشرات كائنات كاملة في ذاكرة لغة جافا الافتراضية (JVM)، وهي عملية ذات بصمة تخزينية باهظة تسبب عبئاً إضافياً على مجمع المهملات (Garbage Collector)، يتم تمثيل صفوف البيانات في هياكل ذاكرة ثنائية غير تابعة للغة جافا (Off-Heap Binary Memory). في هذا السياق، يُخصص بت واحد (Bit) لكل حقل للدلالة على ما إذا كانت قيمته فارغة، مما يسرع عمليات الفحص الشرطي على مستوى المعالج الدقيق عبر الاستفادة من التعليمات المتجهة والتعامل المباشر مع الذاكرة الأولية.

ينعكس وجود القيم المفقودة بشكل مباشر على كفاءة تقسيم البيانات (Data Partitioning) والعمليات التجميعية الموزعة (Aggregations). فخلال تنفيذ عمليات الربط الحوسبي (Joins) أو التجميع بواسطة مفتاح (GroupBy)، يُصنف محرك سبارك السجلات ذات المفاتيح الفارغة في موضع موحد غالباً، مما يؤدي إلى ظاهرة انحراف البيانات (Data Skew). يتسبب هذا الانحراف في إرسال ملايين الصفوف الحاوية على قيم خالية إلى عقدة حوسبية واحدة أثناء مرحلة الخلط (Shuffle Stage)، بينما تنهي باقي العقد مهامها بسرعة وتظل خاملة، الأمر الذي يترتب عليه استهلاك مفرط للذاكرة وربما حدوث أخطاء نفاد الذاكرة (OutOfMemoryErrors) التي تطيح باستقرار خط الأنابيب بأكمله.

2. محدودية دالة fillna() في باي سبارك عند التعامل مع مراجع الأعمدة

2.1 التحليل المصدري لتوقيع دالة fillna والمعاملات المسموحة

عند فحص الكود المصدري لمكتبة باي سبارك ضمن الوحدة pyspark.sql.DataFrameNaFunctions، نجد أن التوقيع البرمجي للدالة fillna(value, subset=None)، والتي تُستدعى أيضاً عبر DataFrame.na.fill()، مصمم للتعامل حصرياً مع قيم استبدال وحيدة ونهائية وثابتة (Scalar Literals). يقبل المعامل value مدخلات محددة تنحصر في الأنماط البدائية: كالأعداد الصحيحة (int)، أو الأعداد العشرية ذات الفاصلة العائمة (float)، أو السلاسل النصية (str)، أو القيم المنطقية (bool)، أو قواميس بايثون (dicts) التي تعين أسماء الأعمدة كمرجع لقيم استبدال ثابتة ومحددة سلفاً لكل عمود على حدة.

تفرض هذه البنية البرمجية قيوداً تصميمية حاسمة تمنع تمرير كائنات الأعمدة (Column Objects)، مثل col("other_column") أو df["other_column"]، كمدخلات بديلة داخل المعامل value. فإذا حاول المطور تنفيذ تعبير مثل df.fillna(df["fallback_column"])، يعترض مفسر لغة بايثون مسار التنفيذ فوراً بإطلاق استثناء نوعي من نمط TypeError أو استثناء معاملات غير قانونية IllegalArgumentException قادم من طبقة جافا التحتية. يرجع هذا السلوك الصارم إلى أن الدالة الداخلية تتوقع قيمة ثابتة محددة يتم حقنها في كتل البيانات التابعة للعمود المستهدف، دون أن تمتلك آليات منطقية لفك ارتباط مؤشر عمود آخر وقراءة قيمه ديناميكياً على مستوى كل صف على انفراد.

تتضح استحالة الاستبدال المعتمد على مراجع الأعمدة المتوازية إذا أدركنا أن دالة fillna() كُتبت في الأساس كدالة مساعدة خفيفة الغرض منها تصفية القيم الخالية بتعويضات ثابتة شائعة (مثل الصفر الحسابي، أو النصوص الافتراضية، أو المتوسطات المحسوبة مسبقاً والممررة كأرقام مجردة). ولا تحتوي هذه الدالة داخل شجرة العمليات المنطقية (Logical Plan) على أدوات تحليل الروابط التعبيرية بين سمات الصف الواحد (Row-level Attribute Resolution)، مما يستلزم اللجوء إلى الدوال التحويلية التعبيرية الأوسع نطاقاً لإنجاز هذا الاستبدال المرجعي الموازي.

2.2 المقارنة التقنية بين سلوك fillna في Pandas وباي سبارك

ينشأ اللبس التقني لدى الكثير من المطورين نتيجة المقارنة المباشرة مع مكتبة بانداس (Pandas) المخصصة للحوسبة أحادية العقدة. في مكتبة بانداس، تتميز دالة DataFrame.fillna() بمرونة معمارية ملحوظة، إذ تسمح بتمرير كائنات السلاسل البيانية (Series) أو مصفوفات البيانات كقيم بديلة. وتستند بانداس في ذلك إلى وجود فهرس مركزي مشترك (Index) يتم محاذاته في الذاكرة المشتركة للمعالج، مما يتيح استبدال القيم الخالية في العمود A بالقيم المقابلة لها في العمود B على مستوى الفهرس الموحد بخطوة برمجية واحدة ودون تعقيد، نظراً لأن الذاكرة كلها متاحة ومحكومة بكتلة معمارية واحدة.

على النقيض من ذلك، تتجذر هياكل البيانات في باي سبارك ضمن مفهوم الأطر الموزعة وغير القابلة للتغيير (Immutable Distributed DataFrames). فلا توجد في سبارك فهارس مركزية دائمة ومحاذاة خطياً في الذاكرة، كما لا يمكن تعديل بيانات أي عمود موضعياً (In-place Mutation). إن أي تعديل على إطار البيانات في سبارك لا يعدو كونه بناءً جديداً لتحويل تعبيري يُضاف إلى الرسم البياني الموجه غير الدوري (Directed Acyclic Graph – DAG) لمسار معالجة البيانات، والذي سيتم تحليله وترجمته لاحقاً إلى كود برمجي فائق السرعة عبر مشروع تونغستن.

تفرض هذه الفروق المعمارية حتمية الانتقال من التفكير القائم على المعالجة الإجرائية السلسة الشائعة في بانداس إلى التفكير التعبيري التصريحي (Declarative Expression Processing) المعتمد في أنظمة الحوسبة الموزعة. فبدلاً من السعي وراء إجبار دوال القيم الثابتة على أداء مهام مراجع الأعمدة، يتعين على المهندس استخدام التعبيرات الحوسبية المستقلة لكل سطر، والتي تقرأ وتدمج السمات المختلفة لنفس الصف بفاعلية رياضية لا تتطلب نسخ الذاكرة ولا تخل بمبدأ الحوسبة الكسولة الصارم في سبارك.

3. الحل المعياري: الاستعانة بدالة coalesce كبديل وظيفي

3.1 الأسس الرياضية والمنطقية لعمل دالة coalesce التحليلية

تُعد دالة coalesce، المستوردة من الوحدة pyspark.sql.functions، الحل المعياري الأمثل والأكثر فصاحة برمجية لتعويض القيم الفارغة بين الأعمدة المتوازية. تستند هذه الدالة في أصلها الرياضي إلى المنطق متعدد القيم، وهي تماثل بنيوياً الدالة المعيارية المتطابقة في مواصفات لغة الاستعلامات البنيوية (ANSI SQL). يتمثل المبدأ التشغيلي للدالة في قبول قائمة من المعاملات التعبيرية الممثلة للأعمدة، وتقييمها تتابعياً من اليسار إلى اليمين لكل صف على حدة، وإرجاع أول قيمة لا تكون نتيجتها فارغة (Non-Null Value).

تتميز دالة coalesce بخاصية التقييم المقصر أو الكسول (Short-Circuit Evaluation). فإذا كانت قيمة المعامل الأول غير فارغة في الصف الجاري معالجته، يُرجع المحرك هذه القيمة فوراً دون تكبد أي عبء حسابي لتقييم أو قراءة المعاملات اللاحقة في القائمة. يقلل هذا السلوك المنطقي استهلاك دورات المعالج الدقيق (CPU Cycles) إلى الحد الأدنى، متجنباً أي عمليات تفرع شرطي مجهدة أو مسارات فحص إضافية غير ضرورية، وهو ما يمنحها كفاءة حسابية فائقة تفوق كافة البدائل الأخرى المبنية على المقارنات المنطقية المباشرة.

من الناحية التركيبية لمُحسِّن الاستعلامات التحفيزي، تُترجم دالة coalesce مباشرة إلى تعبير أساسي منخفض المستوى داخل نواة المحرك يُدعى تعبير الاندماج (Coalesce Expression). لا يفرض هذا التعبير أي كلفة إضافية لإنشاء كائنات جديدة، بل يعمل كمسار تدفق بيانات مباشر يمرر مراجع الذاكرة المتاحة دون تأخير، مما يحافظ على سرعة تنفيذ متطابقة مع أسرع العمليات الحسابية المباشرة المنفذة على مستوى البت في أطر البيانات.

3.2 التكامل بين withColumn وcoalesce لتحقيق الاستبدال المستهدف

لتحقيق التعويض المستهدف بين عمودين، يتم دمج دالة coalesce مع الدالة الهيكلية withColumn. تتيح دالة withColumn إضافة عمود جديد إلى إطار البيانات أو استبدال عمود موجود في حال تطابق التسمية. وتتمثل الصياغة البرمجية المنهجية لهذه العملية في إعادة تعريف العمود الأصلي الذي يعاني من انقطاعات عبر تمريره كمعامل أول في دالة coalesce، متبوعاً بالعمود الاحتياطي كمعامل ثانٍ، كما هو موضح في البنية التالية:

df = df.withColumn("target_col", coalesce(col("target_col"), col("fallback_col")))

تضمن هذه الصياغة الحفاظ الكامل على سلامة مخطط البيانات (Schema Preservation). فالعمود الناتج يحتفظ باسمه الأصلي وموقعه المنطقي وعلاقاته المرجعية دون الإخلال بالمخطط العام لإطار البيانات، شريطة أن تتطابق الأنواع البيانية أو تكون قابلة للترقية النوعية التلقائية. كما تجنب هذه الطريقة الحاجة لإنشاء أسماء أعمدة مؤقتة ثم حذفها، وتوفر كوداً برمجياً مقروءاً وخالياً من التعقيدات التركيبية التي تشوب الأنماط الأخرى.

علاوة على ذلك، يضمن هذا التكامل استقرار خط أنابيب المعالجة واستمراره ضمن بيئة الحوسبة الموزعة دون إجبار النظام على تفريغ البيانات إلى الذاكرة المحلية لجهاز القيادة (Driver Memory). تظل العملية برمتها محصورة في هيئة تحويل تعبيري (Narrow Transformation)، حيث يتم استبدال القيم داخل كل قسم بياني باستقلالية تامة عن باقي الأقسام، مما يعصم خط المعالجة من مشكلات الذاكرة ويضمن قابلية التوسع الخطي (Linear Scalability) مع نمو حجم البيانات من الجيجابايت إلى البيتابايت.

4. إعداد بيئة العمل وبناء مجموعة البيانات الاختبارية

4.1 تهيئة جلسة العمل وإنشاء SparkSession للأغراض التجريبية

تتطلب كتابة واختبار أكواد المعالجة الموزعة في باي سبارك إنشاء جلسة عمل معيارية ممثلة في كائن SparkSession، وهو نقطة الدخول الموحدة لكافة قدرات سبارك منذ إطلاق الإصدار الثاني. يتم ضبط إعدادات الجلسة للعمل في الوضع المحلي (Local Mode) مع توظيف كامل الأنوية الحسابية المتاحة على المعالج المضيف، مما يوفر بيئة تجريبية محاكية لعناقيد الحوسبة الإنتاجية ولكن بحدود موارد محلية قابلة للتحكم والمراقبة الصارمة.

يتضمن الإعداد المعياري استيراد الحزم البرمجية الضرورية والمسؤولة عن التعبيرات الوظيفية والأنواع الهيكلية. نقوم باستيراد وحدة الدوال التعبيرية pyspark.sql.functions مع إعطائها اسماً مختصراً شائعاً مثل F، بالإضافة إلى استيراد الأنواع الهيكلية من pyspark.sql.types لبناء المخططات الصريحة. كما يوصى دوماً بالتحقق البرمجي من إصدار محرك سبارك لضمان التوافق السلوكي للتحسينات التعبيرية المطبقة وتجنب أي تعارض في الخصائص المحدثة، كما يوضح المسار المنهجي التالي:

يتم استدعاء النمط البنائي لإنشاء الجلسة بتحديد اسم التطبيق وضبط حجم الذاكرة المخصصة:

from pyspark.sql import SparkSession
import pyspark.sql.functions as F
from pyspark.sql.types import StructType, StructField, StringType, DoubleType, IntegerType
spark = SparkSession.builder.appName("ImputationDemo").master("local[*]").config("spark.driver.memory", "4g").getOrCreate()

4.2 بناء وتوليد إطار البيانات التمثيلي المشتمل على قيم مفقودة

لبناء سيناريو اختباري واقعي يعكس تحديات معالجة البيانات، نقوم بإنشاء مجموعة بيانات تمثل سجلات أداء الطلاب أو المتسابقين، حيث يشتمل المخطط على معرف السجل (ID)، والاسم (Name)، والنقاط الفعلية المرصودة (Points)، والنقاط التقديرية البديلة (Points_Estimate). تُصمم هذه البيانات عمداً لتشمل مختلف احتمالات فقدان القيم: صفوف مكتملة، وصفوف ينعدم فيها الحقل الفعلي ويتوفر فيها الحقل التقديري، وصفوف ينعدم فيها الاثنان معاً، لاختبار الحالات الحدية للحلول المقترحة.

يتطلب النهج الهندسي الرصين تحديد المخطط البنيوي الصريح (Explicit Schema) بدلاً من الاعتماد على الاستدلال التلقائي للأنواع (Schema Inference)، لضمان التحكم الكامل في خاصية قابلية الإلغاء (Nullable Flag) لكل حقل. يتم تعريف الحقول باستخدام StructField مع تعيين المعامل المنطقي للقابلية للفراغ إلى True، كما يظهر في الخطوات الإجرائية التالية:

schema = StructType([
    StructField("id", IntegerType(), False),
    StructField("name", StringType(), True),
    StructField("points", DoubleType(), True),
    StructField("points_estimate", DoubleType(), True)
])

data = [
    (101, "أحمد", 88.5, 85.0),
    (102, "فاطمة", None, 92.0),
    (103, "عمر", 74.0, None),
    (104, "مريم", None, 78.5),
    (105, "خالد", None, None)
]

df = spark.createDataFrame(data=data, schema=schema)

عند فحص البيانات بصرياً باستخدام دالة df.show() والتحقق من المخطط عبر df.printSchema()، يتجلى التحدي بوضوح: يحتوي السجلان (102) و(104) على قيم خالية في عمود النقاط الفعلية مع وجود قيم صالحة في عمود النقاط التقديرية، في حين يفتقر السجل (105) إلى القيمتين معاً، مما يمثل نموذجاً مثالياً لتقييم كفاءة آليات الاستبدال المقترحة.

5. التطبيق الإجرائي لتعويض القيم باستخدام دالة coalesce

5.1 التنفيذ التدريجي لكود الاستبدال بين عمودين متوازيين

يبدأ التطبيق الإجرائي لتعويض القيم الخالية بتطبيق التعبير الوظيفي المعتمد على دالة coalesce لدمج العمودين points وpoints_estimate. يتم تمرير التعبير التحويلي إلى دالة withColumn لإعادة كتابة العمود المستهدف بقيمه المحسوبة حديثاً، كالتالي:

df_imputed = df.withColumn("points", F.coalesce(F.col("points"), F.col("points_estimate")))

عند تتبع مسار تنفيذ هذا التحويل على مجموعة البيانات التجريبية، نلاحظ سلوكاً دقيقاً لكل سجل على حدة:

  • السجل الأول (101): يمتلك قيمة فعلية (88.5)، لذا تُعيد دالة coalesce هذه القيمة مباشرة في المعامل الأول، متجاهلة القيمة التقديرية تماماً.
  • السجل الثاني (102): يفتقر إلى القيمة الفعلية (None)، فتنتقل الدالة فورياً إلى المعامل الثاني وتسترجع القيمة التقديرية (92.0)، محققة الاستبدال بنجاح.
  • السجل الثالث (103): يمتلك قيمة فعلية (74.0)، فتحتفظ بها الدالة دون تأثر بالقيمة الفارغة في العمود البديل.
  • السجل الرابع (104): تُستبدل القيمة الفارغة بالقيمة التقديرية (78.5) بنفس آلية السجل الثاني.
  • السجل الخامس (105): نظراً لكون كلا الحقلين فارغين، تستنفد الدالة قائمة المعاملات المتاحة وتُرجع في النهاية القيمة الخالية None، محافظاً على توصيف غياب القيمة دون توليد أخطاء استثنائية.

للتحقق الإحصائي من اكتمال المصفوفة وتوثيق انخفاض وتيرة الانقطاعات في العمود المستهدف، يُستحسن إجراء استعلام تجميعي يقيس عدد القيم الخالية المتبقية باستخدام التعبير التالي:

df_imputed.select([F.count(F.when(F.col(c).isNull(), c)).alias(c) for c in ["points", "points_estimate"]]).show()

يُظهر الاستعلام بوضوح تقلص عدد القيم الخالية في عمود النقاط من 3 قيم إلى قيمة واحدة فقط (الخاصة بالسجل 105)، مما يؤكد الإنجاز الناجح لعملية التعويض الموازي بدقة متناهية.

5.2 تحليل خطة التنفيذ المادية (Physical Execution Plan)

لفهم الكيفية التي يعالج بها محرك أباتشي سبارك هذا التحويل التعبيري على مستوى العتاد، نقوم باستعراض خطة التنفيذ المادية من خلال استدعاء دالة df_imputed.explain(mode="formatted") أو df_imputed.explain(True). يكشف هذا التحليل عن سلسلة القرارات التقنية التي اتخذها المولد التحفيزي (Catalyst Optimizer) لتحويل الكود البرمجي عالي المستوى إلى تعليمات جافا ثنائية فائقة الأداء.

يظهر في خطة التنفيذ المادية عقدة إسقاط أساسية تُعرف باسم Project [id#0, name#1, coalesce(points#2, points_estimate#3) AS points#10, points_estimate#3]. يشير هذا التوصيف الصريح إلى أن محرك سبارك يتعامل مع العملية برمتها كإسقاط مباشر (ProjectExec) مطبق محلياً على مستوى كل صف داخل نفس القسم الحسابي. ولا وجود في الخطة لأي عقد تشير إلى حدوث خلط للبيانات (Exchange / Shuffle Free)، مما يؤكد أن الاستبدال لا يتطلب إعادة توزيع السجلات عبر شبكة العنقود، مما يوفر النطاق الترددي للشبكة بصورة مطلقة.

علاوة على ذلك، يُظهر فحص الخطة المادية تفعيل تقنية التوليد الكامل للكود البرمجي للمرحلة (Whole-Stage Code Generation). حيث يقوم محرك تونغستن بدمج قراءة البيانات وتطبيق منطق coalesce وإخراج النتيجة ضمن حلقة تكرارية واحدة مكتوبة بلغة جافا دون استدعاءات دوال وسيطة (Function Call Overhead)، مما يقلل استخدام الذاكرة العشوائية ويمنع تشتت المؤشرات، موفراً أداءً يضاهي كتابة خوارزمية معالجة مخصصة ومترجمة بلغة C مباشرة على المصفوفات الثنائية.

6. الاستراتيجية البديلة: استخدام التركيب الشرطي when وotherwise

6.1 البنية التركيبية للتعبير الشرطي when-otherwise في باي سبارك

تمثل التراكيب الشرطية المبنية عبر دالتي when() وotherwise()، والمتوفرة داخل الحزمة pyspark.sql.functions، الاستراتيجية البديلة الأكثر مرونة لدالة coalesce. تحاكي هذه البنية المنطق التعبيري لعبارة CASE WHEN ... THEN ... ELSE ... END الشهيرة في لغة الاستعلامات SQL، حيث تتيح صياغة قواعد تعويض مخصصة ومعقدة تخضع لاختبارات منطقية دقيقة على مستوى السجلات.

تتمثل الصياغة البرمجية لتعويض القيم الفارغة بين عمودين باستخدام هذا الأسلوب في التحقق الصريح مما إذا كانت قيمة العمود الأساسي خالية عبر استدعاء التابع isNull(). فإذا تحقق الشرط، تُمرر قيمة العمود البديل، وإلا يُعاد توجيه القيمة الأصلية للعمود ذاته باستخدام دالة otherwise()، كما في المثال البرمجي التالي:

df_conditional = df.withColumn(
    "points",
    F.when(F.col("points").isNull(), F.col("points_estimate")).otherwise(F.col("points"))
)

عند المقارنة البصرية للمقروئية البرمجية، نجد أن أسلوب coalesce يتفوق في الإيجاز والوضوح الدلالي عندما يكون الهدف مجرد استبدال القيم الخالية دون شروط إضافية. ومع ذلك، يتميز أسلوب when().otherwise() بالشفافية المنطقية العالية، حيث يجعل نية المبرمج واضحة للعيان دون افتراض معرفة مسبقة بخصائص دوال المنطق متعدد القيم، كما يمنح قابلية للتوسع إذا ما تغيرت متطلبات العمل في المستقبل لتشمل شروطاً أكثر تعقيداً من مجرد غياب القيمة.

6.2 حالات الاستخدام المتمايزة التي تتطلب الاعتماد على التعبير الشرطي

على الرغم من الكفاءة الملحوظة لدالة coalesce، إلا أن هناك سيناريوهات عملية واسعة تحتم الاعتماد الحصري على التعبير الشرطي when().otherwise(). يتجلى السيناريو الأول عندما لا تنحصر مشكلة البيانات المفقودة في وجود الرمز NULL الصريح، بل تتعداه لتشمل قيماً اعتباطية اصطلاحية (Sentinel Values) تدل دلالة ضمنية على الفقدان؛ مثل القيم الصفرية غير المنطقية، أو الأرقام السالبة (مثل 999- أو 1-)، أو السلاسل النصية الفارغة (Empty Strings) أو النصوص المحددة كفراغ اصطلاحي مثل “NA” أو “Unknown”. في هذه الحالات، تعجز دالة coalesce عن اكتشاف الفقدان لأن القيمة موجودة تقنياً في الذاكرة، بينما يمكن للتعبير الشرطي فحص هذه الحالات بمرونة تامة:

df_advanced = df.withColumn(
    "points",
    F.when(F.col("points").isNull() | (F.col("points") <= 0.0), F.col("points_estimate"))
     .otherwise(F.col("points"))
)

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

df_weighted = df.withColumn(
    "points",
    F.when(F.col("points").isNull(), F.col("points_estimate") * 0.95)
     .otherwise(F.col("points"))
)

يوفر التركيب الشرطي أيضاً قدرة لا تضاهى على التحكم الدقيق في الأولويات والتفريعات المتشابكة عند تنوع مصادر التعويض وتغير قواعد العمل باختلاف قطاعات البيانات، مثل استخدام منطق استبدال متباين للعملاء القدامى عن العملاء الجدد بناءً على متغير تصنيفي ثالث، وهو ما يستحيل تحقيقه بدالة coalesce المنعزلة.

7. معالجة سيناريوهات الاستبدال التعاقبي عبر أعمدة متعددة

7.1 التعويض التسلسلي المتدرج (Cascading Imputation)

في المشروعات الصناعية المعقدة، نادراً ما تنحصر عملية الاستبدال في عمودين اثنين فقط؛ إذ يفرض الواقع الهندسي بناء هرمية استرجاع بيانات متدرجة تشتمل على عدة مستويات أمان لحماية النموذج من الانقطاعات. يُطلق على هذا النمط التقني "التعويض التسلسلي المتدرج" (Cascading Fallback Hierarchy). ففي بيئات التجارة الإلكترونية أو التحليلات المالية مثلاً، قد تبدأ الأولوية بمحاولة استرجاع السعر النهائي الفعلي المسجل للسلعة، فإذا كان مفقوداً، يتم الانتقال إلى السعر التقديري للمتجر، ثم إلى متوسط سعر الفئة في المنطقة الجغرافية، وصولاً في حال انعدام الجميع إلى القيمة المركزية العامة للنظام ككل.

تثبت دالة coalesce تفوقاً استثنائياً في إدارة هذا التعاقب المتعدد بفضل قدرتها الطبيعية على استيعاب عدد غير محدود من المعاملات التعبيرية الممررة إليها. يتم ترتيب الأعمدة داخل الدالة من اليسار إلى اليمين وفق الهرمية التنازلية للأولويات، كما في الصياغة البرمجية التالية:

df_cascade = df.withColumn(
    "points",
    F.coalesce(
        F.col("points"),
        F.col("points_estimate"),
        F.col("points_regional_avg"),
        F.lit(50.0)
    )
)

يضمن تضمين الدالة الثابتة lit(50.0) في نهاية سلسلة التعاقب الحسابي القضاء النهائي على أي إمكانية لبقاء حقول فارغة، حتى في الحالات الحدية التي تكون فيها جميع الأعمدة المتوازية معدومة. هذا التدفق المتسلسل يضمن حماية تامة لخوارزميات التعلم الآلي اللاحقة التي قد تنهار برمجياً عند مصادفتها لأي قيمة NULL، مع الحفاظ على كفاءة خط التنفيذ عبر الاستفادة من مبدأ التقييم المقصر للدالة.

7.2 أتمتة عملية التعويض على مستويات واسعة من السمات

عندما تشتمل مجموعات البيانات على مئات السمات المتوازية (مثل مجموعات البيانات الجينومية أو ميزات أجهزة الاستشعار في إنترنت الأشياء)، يصبح تكرار تعليمات withColumn يدوياً لكل عمود عملاً غير كفؤ، وربما يتسبب في مشاكل خطيرة في الذاكرة. فكل استدعاء متتالي لدالة withColumn يضيف طبقة جديدة إلى شجرة خطة التحليل المنطقي (Logical Plan Tree) في سبارك، مما قد يقود إلى خطأ فيضان مكدس الذاكرة (StackOverflowError) في مفسر جافا أثناء مرحلة تحليل وتصريف المخطط البياني.

تتمثل الممارسة الهندسية الرصينة لأتمتة هذه المعالجة على نطاق واسع في استخدام التكرار التعبيري المدمج داخل استدعاء إسقاط واحد عبر دالة select أو استخدام دالة التخفيض reduce من مكتبة functools. في هذا السياق، يمكن تعريف قاموس إعدادات يحدد لكل سمة العمود البديل المخصص لها، وتوليد تعبيرات الاستبدال آلياً كما يوضح المثال التالي:

from functools import reduce
imputation_mapping = {
    "temperature": "sensor_b_temperature",
    "humidity": "sensor_b_humidity",
    "pressure": "sensor_b_pressure"
}

يتم بناء تعبيرات الإسقاط دفعة واحدة لتفادي تكرار التحويلات المؤجلة:

expressions = [
    F.coalesce(F.col(target), F.col(fallback)).alias(target)
    if target in imputation_mapping else F.col(target)
    for target in df.columns
]
df_batch_imputed = df.select(*expressions)

يحافظ هذا الأسلوب المولد للتعبيرات دفعة واحدة على إبقاء شجرة التحليل مسطحة وذات عمق أدنى، مما يمنع استنزاف ذاكرة المترجم ويسرع وقت التجهيز والتحليل إلى أجزاء من الثانية، حتى في الجداول العريضة التي تحوي مئات الأعمدة.

8. إدارة تكافؤ الأنواع وتجنب أخطاء عدم توافق المخطط البنيوي

8.1 قواعد التوافق النوعي الصارم بين الأعمدة في دوال التعبير

يفرض محرك الاستعلامات التحفيزي في أباتشي سبارك نظام فحص أنواع شديد الصرامة (Strict Type Checking) لضمان اتساق البيانات عبر البيئة الموزعة. تشترط دالة coalesce، وكذلك التراكيب التعبيرية للدالة when().otherwise()، أن تكون كافة الأعمدة والمخرجات الممررة متطابقة تماماً في النوع البياني أو قابلة للترقية النوعية التلقائية والضمنية المتوافقة مع معايير الأمان الحسابي (Type Coercion Rules).

فإذا حاول مهندس البيانات دمج عمود من النوع الرقمي الصحيح (IntegerType) مع عمود بديل من النوع النصي (StringType)، سيرفض المحرك التحفيزي تصريف شجرة العمليات ويطلق استثناء تحليلياً صريحاً AnalysisException ينص على تعذر حل النزاع النوعي بين الحقول، كما في الرسالة الشهيرة: "cannot resolve 'coalesce(colA, colB)' due to data type mismatch". لا يقوم سبارك بتحويل النصوص إلى أرقام أو العكس تلقائياً لتفادي وقوع أخطاء تشغيلية مفاجئة قد تفسد البيانات الصامتة أو تؤدي إلى إنتاج قيم فارغة كآثار جانبية للتحويل الفاشل.

لتفادي هذه الأخطاء المعيقة في بيئات الإنتاج، يتعين على المهندس اتخاذ إجراءات معالجة استباقية تعتمد على الإسقاط والتحويل القسري للأنواع باستخدام دالة cast(). يتضمن ذلك توحيد فضاءات الأنواع مسبقاً قبل استدعاء الدمج، كما هو موضح أدناه:

df_type_safe = df.withColumn(
    "points",
    F.coalesce(
        F.col("points").cast(DoubleType()),
        F.col("points_estimate").cast(DoubleType())
    )
)

تضمن هذه الخطوة تطابق النطاق التخزيني للحقول وتمنح استقراراً مطلقاً لعملية التقييم، محيدة أي انحرافات قد تنشأ عن التحميل غير المتسق للبيانات من المصادر الخام كملفات CSV أو واجهات برمجة التطبيقات ذات الأنواع غير المنضبطة.

8.2 التعامل مع الأنواع البيانية المعقدة والمصفوفات الهيكلية

يتجاوز العمل في هندسة البيانات الحديثة معالجة الجداول المسطحة البسيطة؛ إذ غالباً ما تُخزن المعلومات في هياكل بيانات معقدة وشبه مهيكلة (Nested and Complex Types)، مثل الهياكل الفرعية StructType، والمصفوفات ArrayType، وخرائط المفاتيح والقيم MapType. وتثير محاولة تعويض القيم المفقودة داخل هذه الحقول المتداخلة تحديات إضافية تتطلب حلولاً متقدمة تتجاوز الاستبدال السطحي للأعمدة الرئيسية.

عند الرغبة في استبدال حقل فرعي موجود داخل كائن هيكلي (Struct Field) بقيمة حقل موازٍ، لا يمكن تطبيق دالة withColumn التقليدية دون إعادة بناء الكائن الهيكلي بأكمله. في الإصدارات الحديثة من أباتشي سبارك (ابتداءً من الإصدار 3.1 وما بعده)، تم تقديم دالة مساعدة متقدمة تُعرف باسم withField لتعديل وتحديث الحقول الداخلية مباشرة. يتم دمج هذه الإمكانية مع منطق coalesce كما يلي:

df_nested = df.withColumn(
    "metrics",
    F.col("metrics").withField(
        "score",
        F.coalesce(F.col("metrics.score"), F.col("metrics.predicted_score"))
    )
)

أما في حالة القوائم والمصفوفات البيانية الفارغة، يبرز فارق دلالي حاسم بين القائمة التي لا وجود لها أصلاً (Array is NULL) والقائمة المعرفة التي لا تحتوي على أي عناصر داخلها (Empty Array). يتطلب التعامل مع هذا التمييز الجمع بين التحقق من القيمة الصفرية للمصفوفة واستخدام دوال مثل size() لتحديد الفراغ الحقيقي واستبداله بالمصفوفة البديلة دون التأثير على البيانات الوصفية (Metadata) المرتبطة بالمخطط البنيوي العام لإطار البيانات الموزع.

9. اعتبارات الأداء وتحسين استهلاك الموارد في المجموعات الموزعة

9.1 تحليل التعقيد الحسابي وتأثير الاستبدال على زمن الاستجابة

من زاوية التعقيد الحسابي النظري ومعدلات استهلاك الموارد، تصنف عمليات الاستبدال التعبيري المعتمدة على دالتي coalesce وwhen().otherwise() كعمليات ذات تعقيد زمني خطي O(N) نسبة لعدد الصفوف، وتعقيد مكاني مستقر O(1) لكل عامل تشغيلي (Executor)، نظراً لعدم حاجتها إلى الاحتفاظ بحالات سابقة في الذاكرة (Stateless Operations). ومع ذلك، فإن الفوارق الدقيقة في آليات التنفيذ الداخلي لمحرك سبارك تنعكس بوضوح على زمن الاستجابة عند معالجة مليارات السجلات.

تتمتع دالة coalesce بميزة تفوق ملموسة على التعابير الشرطية المعقدة في زمن التجميع والتنفيذ. فالمولد التحفيزي يترجم تعبير الاندماج إلى كود جافا أصلي مباشر وبسيط للغاية، بينما تتطلب التعابير الشرطية بناء تفرعات منطقية (Branching Logic) على مستوى البايت كود (Bytecode). هذا التعقيد في التفرعات الشرطية قد يتجاوز حدود الحجم المسموح به للميثود في محرك جافا (حد الـ 64 كيلوبايت لمترجم Janino الداخلي في سبارك)، مما يعطل ميزة توليد الكود الكامل للمرحلة (Whole-Stage Code Generation) ويجبر المحرك على الرجوع للوضع التفسيري الأبطأ، مما يؤدي إلى تضاعف أزمنة المعالجة.

ولتفادي تراكم التحويلات المؤجلة في مسارات المعالجة الطويلة (Long Lineage Graphs)، والتي قد تؤدي إلى انهيار المحرك أو استنزاف الذاكرة العشوائية السريعة أثناء إعادة حساب التعبيرات عند الفشل، يُوصى بحفظ البيانات مرحلياً عند المحطات الحرجة. يمكن استخدام الحفظ المؤقت في الذاكرة والقرص df.persist() أو استخدام تقنية قطع خط النسب من خلال نقاط التفتيش (Checkpointing) لكتابة البيانات على مساحات التخزين الدائمة مثل نظام هادوب للملفات الموزعة (HDFS) أو أمازون S3، مما يعيد ضبط شجرة التعبيرات ويحرر موارد النظام بالكامل.

9.2 تأثير الاستبدال على ضغط البيانات وتخزينها بتنسيق Parquet

يمتد تأثير استراتيجيات ملء البيانات المفقودة إلى ما وراء زمن التنفيذ ليشمل الكفاءة التخزينية وسرعة القراءة اللاحقة عند حفظ النتائج بتنسيقات التخزين العمودية الحديثة مثل أباتشي باركيه (Apache Parquet) أو أو آر سي (ORC). تستفيد هذه التنسيقات بشكل هائل من تقنيات الضغط والترميز المتقدمة، مثل ترميز القاموس (Dictionary Encoding)، والترميز بطول التشغيل (Run-Length Encoding - RLE)، وترميز حزم البتات (Bit-Packing).

عندما تُترك الأعمدة بنسب فراغ عالية وعشوائية، تضطر محركات التخزين العمودي إلى تخصيص مساحات إضافية لخرائط تعريف المستويات والبتات الصفرية (Definition Levels). وعند إجراء الاستبدال والتعويض بين الأعمدة، تتقارب قيم العمود البديل مع النمط التكراري للبيانات المحيطة، مما يرفع كفاءة ترميز القواميس ويقلل الحجم الفيزيائي النهائي للملفات المضغوطة على الأقراص بنسب تصل أحياناً إلى 30% مقارنة بالملفات التي تعاني من انقطاعات متناثرة.

بالإضافة إلى تقليص الحجم التخزيني، ينعكس هذا التحسين طردياً على تسريع استعلامات القراءة اللاحقة من خلال تفعيل ميزة تخطي مجموعات الصفوف (Row Group Skipping) وتجاوز فهارس الكتل. فعند خلو الأعمدة من التشوهات وتجانس نطاقات القيم، تستطيع المحركات التحليلية الاستفادة الكاملة من إحصائيات الحد الأدنى والأقصى (Min/Max Statistics) المحفوظة في البيانات الوصفية لملف الباركيه لتخطي قراءة ملايين الصفوف التي لا تطابق شروط الاستعلامات، مما يرفع كفاءة عمليات التحليل الاستكشافي اللاحقة بأضعاف مضاعفة.

10. أفضل الممارسات المنهجية وحوكمة تنظيف البيانات في بيئات الإنتاج

10.1 التدقيق والتتبع الإحصائي لعمليات تعديل البيانات

تفرض المعايير الحديثة لحوكمة البيانات والامتثال للأطر التنظيمية (مثل اللائحة العامة لحماية البيانات GDPR أو متطلبات الرقابة المالية الصارمة) عدم تعديل البيانات أو تعويض النواقص في بيئات الإنتاج بصورة صامتة وغير موثقة. إن الاستبدال الخفي للقيم الخالية دون ترك أثر تدقيقي يحرم المحللين وعلماء البيانات اللاحقين من التمييز بين القيم الفعلية المرصودة واقعياً وتلك المستنتجة أو المنقولة من مصادر بديلة، مما قد يؤدي إلى استنتاجات خاطئة أثناء تدريب نماذج الذكاء الاصطناعي.

تتمثل الممارسة القياسية المثلى في إنشاء مؤشرات ثنائية للتتبع (Boolean Imputation Flags) بالتزامن مع عملية التعويض. يُضاف عمود منطقي جديد يسجل القيمة True إذا تم تعديل الحقل أو ملؤه من العمود البديل، وFalse إذا ظلت القيمة الأصلية على حالها، كما توضح الصياغة البرمجية الرصينة التالية:

df_governed = df.withColumn(
    "points_imputed_flag",
    F.col("points").isNull() & F.col("points_estimate").isNotNull()
).withColumn(
    "points",
    F.coalesce(F.col("points"), F.col("points_estimate"))
)

يتيح هذا التوثيق البنيوي إجراء تدقيق إحصائي دوري لحساب معدلات التغيير، ورصد أي انزياح محتمل في التوزيع التكراري للقيم (Distributional Drift)، والتأكد من أن عملية الاستبدال لم تُخل بالمقاييس الإحصائية الجوهرية كالمتوسط والانحراف المعياري للمجتمع البياني. كما يضمن الامتثال الكامل لمبادئ قابلية التدقيق العلمي وإعادة إنتاج التجارب الحسابية (Reproducibility) بدقة متناهية.

10.2 التصميم المعياري لأنابيب تنظيف البيانات الضخمة الموثوقة

لضمان استدامة خطوط أنابيب معالجة البيانات الضخمة وسهولة صيانتها داخل المؤسسات، يجب التخلي عن كتابة الأكواد المتناثرة والتوجيه المباشر نحو تبني نمط التصميم المعياري (Modular Architecture). يتمثل هذا النمط في تغليف منطق التعويض والاستبدال بالكامل داخل دوال برمجية محكمة، قابلة لإعادة الاستخدام، وقابلة للاختبارات الوحدوية الصارمة (Unit Testing) باستخدام أطر الفحص الحديثة مثل pytest ومكتبات تدقيق هياكل سبارك مثل chispa.

يجب أن تشتمل هذه الدوال المعيارية على آليات دفاعية للتعامل السليم مع الاستثناءات وأخطاء وقت التشغيل. يشمل ذلك التحقق الاستباقي من وجود الأعمدة المستهدفة داخل إطار البيانات الممرر، وتطابق أنواعها، قبل الشروع في بناء شجرة التعبيرات، مع إطلاق رسائل استباقية وتوثيقية ذات معنى للمطورين بدلاً من الاعتماد على انهيار المحرك غير المفسر، كما يظهر في التصميم البرمجي المرجعي التالي:

from pyspark.sql import DataFrame
from typing import List
def safe_column_imputation(df: DataFrame, target_col: str, fallback_col: str) -> DataFrame:
    missing_cols = [col for col in [target_col, fallback_col] if col not in df.columns]
    if missing_cols:
        raise ValueError(f"الأعمدة التالية غير موجودة في إطار البيانات: {missing_cols}")
    target_type = df.schema[target_col].dataType
    fallback_type = df.schema[fallback_col].dataType
    if target_type != fallback_type:
        raise TypeError(f"عدم تطابق نوعي: {target_col} ({target_type}) مقابل {fallback_col} ({fallback_type})")
    return df.withColumn(
        f"{target_col}_was_imputed",
        F.col(target_col).isNull() & F.col(fallback_col).isNotNull()
    ).withColumn(
        target_col,
        F.coalesce(F.col(target_col), F.col(fallback_col))
    )

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

خاتمة

استعرض هذا المقال الموسع الإشكالية التقنية المرتبطة بمحدودية دالة fillna() في باي سبارك عند الرغبة في ملء القيم المفقودة استناداً إلى مراجع أعمدة أخرى موازية. وقد تبين أن هذه المحدودية ليست عيباً برمجياً أو سهواً تصميمياً، بل هي نتيجة حتمية للمبادئ المعمارية التي تقوم عليها الحوسبة الموزعة في محرك أباتشي سبارك؛ حيث تفصل النواة الحسابية بصرامة بين استبدال القيم الحرفية الثابتة والتحويلات التعبيرية المطبقة عبر شجرة التعبيرات الكسولة.

وقد أثبت التحليل المنهجي أن دالة coalesce تمثل الحل المعياري والوظيفي الأمثل لإنجاز هذا الاستبدال المرجعي الموازي، مستفيدة من التقييم المقصر، وخلو خطة التنفيذ من عمليات خلط البيانات المكلفة، والتكامل التام مع مشروع تونغستن لتوليد الأكواد الثنائية فائقة السرعة. وفي المقابل، تظل الاستراتيجية المبنية على التراكيب الشرطية when().otherwise() الأداة الأساسية الأكثر فاعلية عندما يقترن الاستبدال بشروط عمل منطقية مركبة، أو قيود على القيم الاعتباطية، أو تحويلات حسابية إضافية على المتغير البديل.

إن إتقان هذه المنهجيات الهندسية، مع مراعاة قواعد تكافؤ الأنواع البيانية، وأتمتة التعبيرات عبر الجداول العريضة، وإدراج مؤشرات التتبع التدقيقي لحوكمة البيانات، يتيح لمهندسي وعلماء البيانات تشييد خطوط معالجة متطورة تتسم بأعلى معايير الاستقرار والكفاءة وقابلية التوسع الأفقي في بيئات الإنتاج الضخمة والمعقدة.

المراجع

  • Armbrust, M., Xin, R. S., Lian, C., Huai, Y., Liu, D., Bradley, J. K., Meng, X., Kaftan, T., Franklin, M. J., Ghodsi, A., & Zaharia, M. (2015). Spark SQL: Relational data processing in Spark. In Proceedings of the 2015 ACM SIGMOD International Conference on Management of Data (pp. 1383–1394). Association for Computing Machinery. https://doi.org/10.1145/2723372.2742797
  • Chambers, B., & Zaharia, M. (2018). Spark: The Definitive Guide: Big Data Processing Made Simple. O'Reilly Media.
  • Little, R. J. A., & Rubin, D. B. (2019). Statistical Analysis with Missing Data (3rd ed.). John Wiley & Sons. https://doi.org/10.1002/9781119482581
  • Rubin, D. B. (1976). Inference and missing data. Biometrika, 63(3), 581–590. https://doi.org/10.1093/biomet/63.3.581
  • Zaharia, M., Xin, R. S., Wendell, P., Das, T., Armbrust, M., Dave, A., Meng, X., Rosen, J., Venkataraman, S., Franklin, M. J., Ghodsi, A., Gonzalez, J., Shenker, S., & Stoica, I. (2016). Apache Spark: A unified engine for big data processing. Communications of the ACM, 59(11), 56–65. https://doi.org/10.1145/2934664

تقييم هذا المحتوى

كن أول من يقيّم هذا المحتوى

اقتباس هذا المقال

looti, M. (2026, أكتوبر 28). باي سبارك: كيفية استخدام fillna() مع عمود آخر. عرب سايكلوجي. https://arabpsychology.com/statistics/pyspark-how-to-use-fillna-with-another-column/
looti, Mohammed. “باي سبارك: كيفية استخدام fillna() مع عمود آخر.” عرب سايكلوجي, 28 أكتوبر 2026, https://arabpsychology.com/statistics/pyspark-how-to-use-fillna-with-another-column/.
looti, Mohammed. “باي سبارك: كيفية استخدام fillna() مع عمود آخر.” عرب سايكلوجي. أكتوبر 28, 2026. https://arabpsychology.com/statistics/pyspark-how-to-use-fillna-with-another-column/.