كيفية جمع أعمدة متعددة في PySpark (مع مثال)

دليل أكاديمي شامل يشرح كيفية جمع أعمدة متعددة في إطار بيانات PySpark باستخدام التعبيرات الحسابية الموزعة، مع أمثلة برمجية ومعالجة القيم المفقودة وتحسين الأداء.

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

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

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

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

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

1. مقدمة تأصيلية لمفهوم جمع الأعمدة في أطر معالجة البيانات الضخمة (PySpark)

1.1 التحديات الحسابية في بيئات الحوسبة الموزعة

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

تتمثل إحدى أهم العقبات التشغيلية في هذه البنى التحتية في إدارة حركة البيانات عبر الشبكة، وهي العملية المعروفة باسم خلط البيانات (Data Shuffling). يحدث خلط البيانات عندما تتطلب العملية الحسابية إعادة توزيع السجلات عبر الأقسام لجمع بيانات تشترك في مفتاح معين، مما يستنزف سعة النطاق الترددي للشبكة ويولد اختناقات زمنية حادة في الإدخال والإخراج. تتميز العمليات الحسابية المطبقة أفقياً على مستوى الصف الواحد—مثل جمع أعمدة متعددة ضمن نفس السجل—بأنها تندرج تحت ما يُسمى بالتحويلات الضيقة (Narrow Transformations).

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

1.2 الفارق الجوهري بين الجمع التجميعي (الرأسي) والجمع الأفقي (على مستوى السجل)

يخلط كثير من المطورين المبتدئين في بيئة PySpark بين مفهومين رياضيين مختلفين تماماً لعملية الجمع: الجمع الرأسي التجميعي (Vertical Aggregation) والجمع الأفقي على مستوى السجل (Horizontal Row-Wise Summation). يشير الجمع الرأسي إلى تطبيق دالة التجميع الرياضية على امتداد صفوف عمود واحد أو أكثر لاختزال آلاف أو ملايين السجلات في قيمة إحصائية واحدة أو مجموعة قيم فرعية بناءً على تقسيم فئوي محدد (مثل استخدام دالة التجميع مع التجميع الفئوي).

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

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

1.3 الأهمية المنهجية لدمج الأعمدة في هندسة البيانات

تمثل هندسة الميزات (Feature Engineering) حجر الزاوية في بناء وتدريب نماذج التعلّم الآلي الفعالة، حيث تسهم جودة المتغيرات المشتقة في تحسين القدرة التنبؤية للنماذج بصورة تفوق في كثير من الأحيان مجرد ضبط المعاملات الفائقة للخوارزميات. يشكل دمج الأعمدة عبر الجمع الأفقي وسيلة رياضية لتوليد مؤشرات رقمية مركبة تعبر عن أداء كلي أو كمية تجميعية موحدة تنشأ من تفاعل متغيرات فرعية متعددة وموزعة في جداول البيانات الأولية.

في معالجة بيانات سلاسل الحركة والمقاييس البيومترية المعقدة، مثل استخلاص السمات الحركية من مصفوفات تتبع حركة المفاصل لتقييم الأداء الميكانيكي (Bertoli et al., 2026)، تبرز الحاجة الملحة لدمج مخرجات مستشعرات متعددة لتمثيل الطاقة الإجمالية أو إجمالي عزم الدوران. كما يُستخدم الجمع الأفقي بشكل واسع لتلخيص القياسات الدورية كحساب إجمالي النفقات المالية من بنود المصروفات المنفصلة، أو جمع إجمالي النقاط المسجلة في ألعاب رياضية متعاقبة.

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

2. البنية المعمارية لـ PySpark وإدارة هياكل البيانات (DataFrames)

2.1 نموذج التنفيذ الكسول (Lazy Evaluation) ودوره في تحسين العمليات

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

تُبنى هذه السلسلة في شكل هيكل بياني يُعرف بالرسم البياني الموجه غير الدائري (Directed Acyclic Graph – DAG). يظل هذا المخطط الحسابي قيد الإنشاء والتوسيع ما دامت الأوامر المدخلة هي تحويلات بيانية، ولا تبدأ الحوسبة الفعلية للمجموع وتوزيع الأعباء على المعالجات إلا عند استدعاء عملية إجرائية قطعية (Action) تتطلب إخراج نتائج ملموسة، مثل طلب عرض البيانات أو حفظ الإطار في صيغة تخزينية دائمة.

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

2.2 محرك التحسين كاتيليست (Catalyst Optimizer) وتعبيرات الحوسبة

يقع محرك كاتيليست (Catalyst Optimizer) في قلب معمارية Spark SQL وواجهات DataFrames البرمجية، وهو المسؤول عن تحويل التعليمات البرمجية التي يكتبها المطور إلى خطط تنفيذ فيزيائية شديدة التحسين. يستقبل كاتيليست العمليات الحسابية المكتوبة بلغة بايثون ويحولها إلى شجرة تعبيرية منطقية (Logical Tree)، حيث يطبق عليها تقنيات الاستمثال المبنية على القواعد (Rule-Based Optimization) والاستمثال المبني على التكلفة (Cost-Based Optimization).

عند صياغة عملية جمع لأعمدة متعددة، يتعامل كاتيليست مع دالة الجمع كشجرة تعبيرية تتضمن مشغلات الحساب منخفضة المستوى. يقوم المحرك بتحليل هذه الشجرة لإجراء تبسيطات رياضية متقدمة وتجنب العمليات الحسابية المكررة، ثم يقوم بتوليد كود منخفض المستوى (Whole-Stage Code Generation) يُنفذ مباشرة على الآلة الافتراضية لجافا عبر محرك تونغستن (Tungsten Execution Engine).

يتجاوز هذا الأسلوب المعماري قيود لغة بايثون المعروفة، مثل قفل المفسر العام (Global Interpreter Lock – GIL) وبطء تنفيذ العمليات الرياضية التكرارية داخل الحلقات. وبفضل هذا التكامل التعبيري، فإن كود جمع الأعمدة الذي يكتبه مطور PySpark يُترجم في نهاية المطاف إلى كود آلي شديد السرعة يعمل بالسرعة الأصلية للغات البرمجة منخفضة المستوى مثل C++ أو جافا، مما يضمن أقصى استغلال ممكن لقدرات وحدات المعالجة المركزية.

2.3 مفهوم الأعمدة والأنواع البيانية داخل مخطط البيانات (Schema)

يمثل كائن العمود (Column Object) في واجهة PySpark مفهوماً مختلفاً جوهرياً عن تمثيله في مكتبات بايثون المحلية مثل Pandas. ففي PySpark، لا يحمل كائن العمود القيم الرقمية الفعلية في الذاكرة المحلية لجهاز المطور، وإنما يعمل كرمز تعبيري غير مقيم (Unevaluated Expression) يحدد كيفية اشتقاق البيانات أو الإشارة إليها داخل محرك الحوسبة الموزع.

تخضع هياكل DataFrames لمخطط بياني محدد مسبقاً (Schema) يصف بدقة نوع البيانات المخزنة في كل عمود، مثل الأعداد الصحيحة بمختلف أطوالها (Byte, Short, Integer, Long) أو الأعداد العشرية ذات الفاصلة العائمة (Float, Double). يلعب هذا المخطط دوراً حاسماً في استقرار العمليات الحسابية؛ حيث يتطلب جمع الأعمدة توافقاً دقيقاً في الأنواع البيانية لمنع حدوث أخطاء وقت التشغيل أو تشويه النتائج العددية.

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

3. الطريقة القياسية: استخدام التعبير الحسابي F.expr لجمع الأعمدة

3.1 التفكيك النحوي لدالة F.expr وآلية عملها التفسيرية

تعتبر دالة F.expr، المتاحة عبر استيراد مكتبة الدوال القياسية في سبارك (pyspark.sql.functions)، إحدى أكثر الطرق أناقة ومرونة لبناء التعبيرات الحسابية المعقدة في PySpark. تتيح هذه الدالة للمطور كتابة تعبيرات SQL أصلية وتمريرها كسلسلة نصية تُفسر مباشرة داخل محرك كاتيليست، مما يلغي الفجوة الإجرائية بين واجهة بايثون والتعليمات الحسابية لبيئة SQL التحليلية.

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

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

3.2 ديناميكية دمج أسماء الأعمدة البرمجية باستخدام join في بايثون

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

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

يحقق هذا الفصل المنهجي بين مصفوفة أسماء الأعمدة وصياغة المعادلة الحسابية مبدأ برمجياً متقدماً يعرف بعدم تكرار الشيفرة البرمجية (Don’t Repeat Yourself – DRY). يتيح هذا النمط تحديث وتوسيع خط أنابيب المعالجة دون الحاجة لتعديل المنطق الحسابي في كل مرة تتغير فيها أسماء الأعمدة أو يزداد عددها، مما يعزز مرونة الكود وموثوقيته في خطوط المعالجة الأوتوماتيكية المؤتمتة بالكامل.

3.3 إضافة العمود المحسوب عبر دالة withColumn

تعد دالة withColumn الأداة الأساسية والأكثر شيوعاً في واجهة PySpark لاشتقاق أعمدة جديدة أو استبدال أعمدة قائمة داخل هياكل DataFrames. تأخذ الدالة وسيطين رئيسيين: الأول هو اسم العمود الجديد المراد إنشاؤه كسلسلة نصية، والوسيط الثاني هو كائن العمود أو التعبير الحسابي الذي يحدد القيمة الرياضية التي سيتم إسنادها لكل سجل.

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

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

4. التطبيق العملي التوضيحي: دراسة حالة بيانات أداء الفرق الرياضية

4.1 تهيئة جلسة العمل (SparkSession) وتجهيز البيئة الحسابية

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

يتم بناء الجلسة عادة باستخدام نمط التصميم الشائع المعروف بنمط الباني (Builder Pattern)، حيث يستدعي المطور التابع SparkSession.builder مع تحديد الخصائص التشغيلية للتطبيق مثل اسم التطبيق ومستوى توزيع الموارد. وفي التطبيقات المحلية والتطويرية، يُضبط النمط الرئيسي للعمل ليشمل كافة الأنوية المتوفرة على الجهاز المعالج لضمان محاكاة البيئة الموزعة بدقة.

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

4.2 تعريف وهيكلة مصفوفة البيانات ومخطط الأعمدة الأولي

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

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

تأتي بعد ذلك خطوة استدعاء دالة createDataFrame التابعة لكائن الجلسة النشط، وتمرير مصفوفة البيانات وقائمة أسماء الأعمدة كمعاملات إدخال. في هذه المرحلة، يقوم سبارك باستنتاج الأنواع البيانية للأعمدة تلقائياً (Schema Inference)، فيحدد العمود الأول كنص رمزي (StringType)، بينما يصنف أعمدة المباريات كأعداد صحيحة (LongType أو IntegerType)، محولاً المصفوفة المحلية إلى إطار بيانات موزع بالكامل وجاهز للعمليات الحسابية.

4.3 استعراض وفحص إطار البيانات الأصلي

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

تتيح المعاينة المباشرة التحقق من صحة الأرقام المسجلة؛ حيث يظهر الفريق ‘A’ مسجلاً للنقاط (10، 15، 8)، والفريق ‘B’ مسجلاً (24، 19، 31)، والفريق ‘C’ مسجلاً (12، 14، 12)، بينما سجل الفريق ‘D’ القيم (14، 8، 12). تكشف هذه المراجعة الأولية تطابق الأبعاد وخلو المدخلات من أي تشوهات تركيبية واضحة في البنية العامة للصفوف.

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

4.4 تطبيق الكود لجمع أعمدة المباريات وتحليل النتيجة النهائية

لتطبيق عملية الجمع الأفقي، نقوم أولاً بتحديد قائمة الأعمدة المستهدفة بحساب المجموع، وهي الأعمدة الثلاثة الخاصة بالمباريات: cols_to_sum = ['game1', 'game2', 'game3']. بعد ذلك، نطبق الأسلوب القياسي المعتمد على دمج السلسلة النصية وتمريرها إلى محرك التعبيرات، وذلك عبر الصياغة البرمجية التالية:

df_with_sum = df.withColumn('total_points', F.expr('+'.join(cols_to_sum)))

يقوم المعامل النصي '+'.join(cols_to_sum) بتوليد التعبير الحسابي النصي "game1+game2+game3". تلتقط دالة F.expr هذا التعبير لتبني شجرة حوسبة رياضية، وتقوم دالة withColumn بإدراج العمود الجديد تحت مسمى total_points ضمن إطار البيانات المشتق الجديد df_with_sum.

عند استعراض النتيجة النهائية عبر استدعاء df_with_sum.show()، يظهر الجدول النهائي متضمناً العمود التراكمي المحسوب بدقة حسابية متناهية لكل صف: حيث يحصل الفريق ‘A’ على مجموع 33 نقطة (10+15+8)، ويحرز الفريق ‘B’ مجموع 74 نقطة (24+19+31)، وينال الفريق ‘C’ مجموع 38 نقطة (12+14+12)، ويستقر الفريق ‘D’ عند 34 نقطة (14+8+12). يؤكد هذا التطابق الحسابي سلامة الخوارزمية المنفذة وقدرتها على استيعاب ومعالجة الأبعاد المتعددة بسلاسة.

5. الطرائق البديلة لجمع الأعمدة المتعددة في PySpark

5.1 الجمع المباشر باستخدام العامل الحسابي الجمعي (+) مع كائنات الأعمدة

تتمثل إحدى أبسط البدائل لجمع الأعمدة في استخدام معامل الجمع الرياضي التقليدي (+) للربط المباشر بين كائنات الأعمدة المستخرجة من إطار البيانات. تتيح هذه الطريقة التعبير عن الحساب بصيغة تشبه المعادلات الجبرية المباشرة، مثل كتابة: df['game1'] + df['game2'] + df['game3']، أو باستخدام الدالة الصريحة للأعمدة F.col('game1') + F.col('game2') + F.col('game3').

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

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

5.2 توظيف الدوال الوظيفية في بايثون: دالة reduce ومعامل operator.add

تمثل البرمجة الوظيفية (Functional Programming) ركيزة فلسفية أساسية في بناء وتصميم أباتشي سبارك، ولذلك فإن توظيف دوال بايثون الوظيفية القياسية ينسجم تماماً مع الطبيعة المعمارية للمنظومة. تبرز دالة reduce من مكتبة functools بالاشتراك مع معامل الجمع operator.add كبديل فائق النقاء البرمجي لبناء تعبيرات الجمع الأفقي التراكمية على قوائم الأعمدة دون الحاجة للتعامل مع السلاسل النصية.

تعمل دالة reduce على تطبيق العملية المحددة (وهي عملية الجمع هنا) بشكل تراكمي ومتتابع على قائمة كائنات الأعمدة [F.col(c) for c in cols_to_sum]. تبدأ الدالة بجمع أول عمودين لإنتاج كائن عمود مركب، ثم تواصل جمع هذا الناتج مع العمود التالي في القائمة، مستمرة في هذه العملية حتى استنفاد كافة عناصر القائمة لإنتاج كائن تعبيري موحد يمثل المجموع التراكمي الشامل لكافة الأعمدة المطلوبة.

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

5.3 استخدام دوال المصفوفات التجميعية: array و aggregate

تقدم واجهة PySpark منهجية متطورة للغاية تعتمد على تحويل مجموعة الأعمدة الرقمية المنفصلة إلى عمود مركب واحد من نوع مصفوفة (ArrayType). يتم هذا التحويل عبر استدعاء دالة F.array() وتمرير قائمة الأعمدة إليها، مما يدمج قيم تلك الأعمدة في كل صف داخل قائمة مصفوفية موحدة يسهل التعامل معها لاحقاً باستخدام دوال التجميع ذات الرتب العليا (Higher-Order Functions).

بمجرد إنشاء عمود المصفوفة، يمكن توظيف دالة F.aggregate() لتطبيق عملية جمع تراكمية على عناصر المصفوفة داخل كل صف بشكل مستقل. تتيح دالة التجميع تحديد القيمة الابتدائية للمجمع التراكمي (صفر)، ثم تطبيق تعبير لامدا (Lambda Expression) يقوم بإضافة كل عنصر في المصفوفة إلى القيمة التراكمية الحالية حتى إتمام الحساب لكافة عناصر الصف.

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

6. معالجة القيم المفقودة (Null Values) وتأثيرها على نتائج الجمع

6.1 السلوك الافتراضي لـ PySpark عند مواجهة قيم Null في العمليات الحسابية

تعتبر معالجة القيم المفقودة (Null Values) إحدى أدق المسائل الرياضية في الحوسبة الإحصائية وإدارة قواعد البيانات الموزعة. يتبع محرك PySpark في عملياته الحسابية الافتراضية معايير لغة SQL القياسية الصارمة فيما يخص التعامل مع القيم الخالية، والتي تُعرف بقاعدة “انتشار القيمة الخالية” (Null Propagation Principle). تنص هذه القاعدة على أن أي عملية جمع حسابية تتضمن قيمة مفقودة واحدة ستؤدي حتماً إلى تحول ناتج العملية برمتها إلى قيمة مفقودة (Null).

إذا كان أحد الصفوف يحتوي على أرقام مسجلة في عمودين وقيمة مفقودة في العمود الثالث، فإن الجمع الأفقي المباشر لتلك الأعمدة الثلاثة سينتج عنه Null بدلاً من جمع القيمتين المتوفرتين. يعود السبب الرياضي وراء هذا السلوك إلى أن القيمة المفقودة في الأنظمة الموزعة تعبر عن حالة من عدم التيقن (Unknown Value)، ورياضياً، فإن إضافة قيمة محددة إلى قيمة غير معلومة يسفر بالضرورة عن ناتج غير معلوم.

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

6.2 استخدام دالة coalesce لتحييد القيم المفقودة برمجياً

تمثل دالة F.coalesce() الحل البرمجي الأمثل والأكثر كفاءة في PySpark للتغلب على إشكالية انتشار القيم الخالية أثناء الحسابات الأفقية. تعمل هذه الدالة على تقييم قائمة من التعبيرات لكل سجل، وإرجاع أول قيمة غير مفقودة (Non-Null) تصادفها في السلسلة. في سياق جمع الأعمدة، تُستخدم الدالة لتغليف كل عمود مستهدف واستبدال قيمته بصفر رقمي صريح في حال كانت القيمة الأصلية مفقودة.

يمكن تطبيق هذه التقنية ديناميكياً على مجمل الأعمدة المستهدفة بالجمع باستخدام فهم القوائم (List Comprehension)، من خلال صياغة تعبير يستبدل كل عمود c بالصيغة: F.coalesce(F.col(c), F.lit(0)). يتم بعد ذلك تمرير هذه القائمة المنظفة من القيم المفقودة إلى دالة التراكم الرياضي، مما يضمن احتساب القيم المتوفرة وتجاهل الفجوات البيانية بأمان تام ودون المخاطرة بتحول الناتج الكلي إلى Null.

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

6.3 التوظيف الشرطي باستخدام دوال when و otherwise لمعالجة الحالات الخاصة

في بعض السيناريوهات المتقدمة في هندسة البيانات والتحليلات الطبية والبيولوجية المعقدة، مثل نمذجة الإشارات الفسيولوجية لتمييز المشاعر والأنماط المعقدة (Doma & Pirouz, 2020)، قد لا يكون استبدال القيمة المفقودة بالصفر كافياً أو ملائماً من الناحية العلمية. في مثل هذه الحالات، يتطلب منطق المعالجة تطبيق شروط منطقية صارمة تعتمد على دوال التفرع الشرطي في سبارك، وتحديداً الدالتين F.when() و F.otherwise().

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

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

7. التعامل مع تباين الأنواع البيانية والتحويل القسري (Type Casting)

7.1 التفاعل بين الأنواع الرقمية غير المتجانسة أثناء الجمع

تواجه عمليات جمع الأعمدة في مجموعات البيانات الواقعية تحدياً يتمثل في تباين الأنواع الرقمية المخزنة بين الأعمدة المراد دمجها؛ حيث قد يكون أحد الأعمدة مخزناً كعدد صحيح قصير (ShortType)، بينما يخزن عمود آخر كعدد صحيح طويل (LongType)، ويخزن عمود ثالث كعدد عشري مضاعف الدقة (DoubleType). يمتلك محرك أباتشي سبارك منظومة داخلية مدمجة لإدارة هذه التباينات تُعرف بقواعد “الترقية التلقائية للأنواع” (Type Coercion / Promotion).

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

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

7.2 التحويل الصريح للأعمدة النصية التي تحتوي على أرقام

تصل البيانات في كثير من الأحيان من مصادر أولية مهتزة أو ملفات نصية بتنسيقات مثل CSV أو خوادم سجلات الأحداث، حيث تُخزن بعض القيم الرقمية كحقول نصية (StringType) بدلاً من أنواعها العددية الصحيحة. إذا حاول المطور إجراء جمع مباشر لأعمدة رقمية بعضها مخزن كنصوص، فإن بيئة PySpark ستتصرف وفق قواعد السلاسل النصية، مما يؤدي إلى إجراء دمج نصي (String Concatenation) بدلاً من الجمع الحسابي المطلوب.

فعلى سبيل المثال، يؤدي جمع القيمة العددية 10 مع القيمة النصية “20” في بعض السياقات إلى حدوث أخطاء استثنائية، أو دمجها لتصبح “1020” بدلاً من الناتج الحسابي الصحيح 30. لتصحيح هذا المسار، يتعين تطبيق التحويل القسري الصريح (Explicit Casting) باستخدام التابع cast() المرتبط بكائنات الأعمدة، كأن يتم تحويل العمود النصي إلى نوع عددي صريح عبر الأمر: F.col('text_column').cast('double').

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

7.3 تفادي أخطاء التدفق الرقمي الحسابي (Numeric Overflow)

يمثل التدفق الرقمي الحسابي (Numeric Overflow) خطراً جسيماً في عمليات الحوسبة الموزعة التي تتعامل مع أرقام ضخمة وسجلات تجميعية متراكمة. تمتلك كافة الأنواع البيانية الصحيحة حدوداً عليا ودنيا صارمة لسعة التخزين محكومة بعدد البتات المخصصة لها في الذاكرة؛ فالنوع الصحيح القياسي (IntegerType) يعتمد على 32 بت، ولا يمكنه استيعاب أرقام تتجاوز قيمتها الحد الأقصى المسموح به برمجياً.

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

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

8. الأداء وقابلية التوسع (Performance and Scalability) في مجموعات البيانات الضخمة

8.1 المقارنة الأدائية بين F.expr وبدائل الأكواد الأخرى

يثور في أوساط مهندسي البيانات نقاش دائم حول الفروق الأدائية بين كتابة العمليات الحسابية باستخدام التعبيرات النصية F.expr مقابل توظيف كائنات الأعمدة الصريحة أو الدوال الوظيفية مثل reduce. لتحليل هذا الفارق بموضوعية علمية، يجب التمييز بين مرحلتين رئيسيتين في دورة حياة التطبيق الحسابي في سبارك: مرحلة التخطيط والتحليل الأولي (Planning Phase)، ومرحلة التنفيذ الفيزيائي الفعلي على العقد الموزعة (Execution Phase).

في مرحلة التحليل الأولي على مستوى برنامج التشغيل (Driver)، يتطلب استخدام F.expr وقتاً إضافياً طفيفاً يُقاس بالمللي ثانية، حيث يحتاج المحرك إلى تحليل السلسلة النصية نحوياً وبناء الشجرة التعبيرية المقابلة لها عبر وحدة تحليل النصوص التابعة لـ Catalyst. في المقابل، فإن استخدام كائنات الأعمدة الصريحة مثل F.col أو reduce يتجاوز هذه الخطوة التحليلية النصية ويبني العقد الشجرية مباشرة داخل الذاكرة.

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

8.2 أثر تضخم عدد الأعمدة المجمعة على ذاكرة برنامج التشغيل (Driver Memory)

على الرغم من قدرة محرك سبارك الفائقة على معالجة مليارات الصفوف بسلاسة، إلا أن زيادة عدد الأعمدة (العرض الأفقي للبيانات) يضع ضغوطاً من نوع خاص على المعمارية الحسابية. عندما يُطلب من المحرك جمع مئات الأعمدة دفعة واحدة داخل تعبير حسابي واحد، تتضخم الشجرة التعبيرية الناتجة لتصل إلى آلاف العقد الفرعية المترابطة داخل الذاكرة الخاصة ببرنامج التشغيل (Driver Program).

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

لمواجهة هذا الاختناق المعماري، يتعين على المهندسين تقسيم عمليات الجمع الضخمة إلى مراحل مجزأة (Chunking / Staging). بدلاً من جمع 500 عمود في تعبير برمجي واحد، يمكن تقسيم الأعمدة إلى مجموعات فرعية متوازنة (مثلاً 50 عموداً في كل مجموعة)، وحساب المجموع الفرعي لكل مرحلة كخطوة وسيطة، ثم جمع المجاميع الفرعية في خطوة نهائية، مما يخفف الحمل الحسابي على محرك التحسين ويضمن استقرار بيئة المعالجة.

8.3 إدارة خطة التنفيذ وتجنب إعادة الحساب عبر التخزين المؤقت (Caching)

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

لتفادي هذا الإهدار الحوسبي غير المبرر، يُعد استخدام آليات التخزين المؤقت الموزع، عبر استدعاء التابع df.cache() أو df.persist()، استراتيجية بالغة الأهمية. يوجه هذا الأمر محرك سبارك إلى الاحتفاظ بنتائج إطار البيانات المحسوب—متضمناً عمود المجموع النهائي—داخل الذاكرة العشوائية الموزعة للعقد العاملة فور اكتمال حسابه في أول إجراء فعلي يتم تنفيذه.

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

9. الأنماط المتقدمة: التحديد الديناميكي والشرطي للأعمدة المستهدفة

9.1 تصفية الأعمدة ديناميكياً بناءً على أنماط التسمية والبادئات

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

باستخدام أسلوب فهم القوائم (List Comprehension) في بايثون، يمكن مسح كافة أعمدة إطار البيانات المتاحة عبر الخاصية df.columns واستخلاص الأعمدة التي تبدأ بنمط نصي محدد بدقة. ففي دراسة الحالة الرياضية السابقة، يمكن استخراج كافة أعمدة المباريات تلقائياً عبر التعبير البرمجي: cols_to_sum = [c for c in df.columns if c.startswith('game')]، دون الحاجة لمعرفة عدد المباريات المسبق سواء كانت ثلاثاً أو ثلاثين مباراة.

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

9.2 التحديد المعتمد على فحص نوع البيانات برمجياً من المخطط (Schema)

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

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

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

9.3 الجمع المشروط للأعمدة وفق شروط منطقية على مستوى السجل

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

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

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

10. أفضل الممارسات الهندسية والتوصيات لكتابة كود PySpark مستدام

10.1 بناء دوال مخصصة قابلة لإعادة الاستخدام (Modular Functions)

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

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

يسهم هذا الأسلوب المعماري في تعزيز قابلية صيانة البرمجيات التحليلية على المدى الطويل؛ فإذا دعت الحاجة مستقبلاً إلى تغيير استراتيجية الجمع—مثل الانتقال من تعبيرات F.expr إلى التوابع الوظيفية أو تعديل معايير معالجة التدفق الرقمي—فإن التعديل يتم في موضع مركزي واحد داخل الدالة المعيارية دون الحاجة للمساس بعشرات السجلات والملفات الموزعة عبر خط أنابيب المعالجة الضخم.

10.2 تصميم اختبارات الوحدة (Unit Testing) للتحقق من سلامة الحسابات

يشكل الاختبار البرمجي المستمر صمام الأمان الأساسي لمنع تسلل الأخطاء الحسابية الكارثية إلى بيئات الإنتاج الحية. في مشاريع PySpark الضخمة، يتعين إخضاع دوال جمع الأعمدة لاختبارات وحدة صارمة (Unit Tests) باستخدام أطر الاختبار المعتمدة في بايثون مثل pytest، للتحقق من دقة النتائج الحسابية تحت مختلف الظروف التشغيلية.

يجب أن تركز اختبارات الوحدة على فحص الحالات الحدية الحرجة (Edge Cases) التي تفشل فيها عادة الحلول البرمجية السطحية. يتضمن ذلك اختبار سلوك الدالة عند تغذيتها بصفوف تحتوي على قيم مفقودة (Nulls) بالكامل، أو صفوف تحوي قيماً صفرية وسالبة، واختبار استجابة النظام عند تمرير أعمدة ذات أنواع بيانية متباينة أو أعمدة نصية تتطلب تحويلاً قسرياً، فضلاً عن التحقق من سلوك الدالة عند تمرير قائمة أعمدة فارغة.

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

10.3 التوثيق البرمجي وإدارة الأخطاء والاستثناءات في بيئات الإنتاج

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

في بيئات الإنتاج الموزعة، ينبغي تغليف العمليات الحساسة بكتل اصطياد الأخطاء المتخصصة (try-except)، للتعامل الواعي مع استثناءات تحليل التعبيرات أو غياب الأعمدة المستهدفة من المخطط البياني. بدلاً من ترك التطبيق ينهار بصورة مفاجئة عند مواجهة عمود مفقود، يمكن للدالة اصطياد استثناء AnalysisException وتسجيل رسالة تشخيصية مفصلة تشرح بدقة سبب الإخفاق وتحدد السجل أو القسم المتأثر.

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

خاتمة

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

أبرزت المقارنات التطبيقية أن استخدام التعبير الحسابي F.expr المدمج مع المعامل النصي join يمثل المنهجية الأكثر مرونة وقياسية في هندسة البيانات؛ حيث يتيح التعامل الديناميكي مع أعداد هائلة من الأعمدة دون المساس بمستوى الأداء النهائي. كما استعرضنا البدائل البرمجية المتنوعة كالجمع المباشر واستخدام دوال البرمجة الوظيفية مثل reduce ومصفوفات العناصر، مما يوفر للمطور أدوات متعددة تناسب مختلف متطلبات التصميم الهندسي.

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

المراجع

Ahnjili Zhuparris, Ghobad Maleki, Liesbeth van Londen, Ingrid W. Koopmans, Vincent Aalten, Iris E. Yocarini, et al. (2023). A smartphone- and wearable-based biomarker for the estimation of unipolar depression severity. Scientific Reports. https://doi.org/10.1038/s41598-023-46075-2

Annalisa Bertoli, Manuela Vargas, Denise Tumiotto, Joao Marcos Da Silva Araujo, Silvia Costi, Simone Orlandini, et al. (2026). An automatic ergonomic evaluation based on human movement recognition from motion capture data with random forest classifiers. Exploration of Musculoskeletal Diseases. https://doi.org/10.37349/emd.2026.1007130

Vikrant Doma, Matin Pirouz (2020). A comparative analysis of machine learning methods for emotion recognition using EEG and peripheral physiological signals. Journal Of Big Data. https://doi.org/10.1186/s40537-020-00289-7

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

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

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

looti, M. (2026, أكتوبر 28). كيفية جمع أعمدة متعددة في PySpark (مع مثال). عرب سايكلوجي. https://arabpsychology.com/statistics/how-to-sum-multiple-columns-in-pyspark-with-example/
looti, Mohammed. “كيفية جمع أعمدة متعددة في PySpark (مع مثال).” عرب سايكلوجي, 28 أكتوبر 2026, https://arabpsychology.com/statistics/how-to-sum-multiple-columns-in-pyspark-with-example/.
looti, Mohammed. “كيفية جمع أعمدة متعددة في PySpark (مع مثال).” عرب سايكلوجي. أكتوبر 28, 2026. https://arabpsychology.com/statistics/how-to-sum-multiple-columns-in-pyspark-with-example/.