تُعد معالجة البيانات واستكشافها الركيزة الأساسية التي يقوم عليها أي تحليل إحصائي رصين أو نموذج تنبؤي دقيق في بيئة الحوسبة الإحصائية المعاصرة. وفي هذا السياق، تبرز لغة البرمجة الإحصائية R كإحدى أقوى وأشمل الأدوات التي طورها المجتمع الأكاديمي والتقني للتعامل مع التحديات المعقدة في تنقيب البيانات والنمذجة الرياضية. ومع ذلك، فإن النقاء المثالي للبيانات لا يمثل سوى حالة نظرية نادراً ما تتحقق في الممارسة الواقعية؛ إذ تعاني مجموعات البيانات الواقعية، سواء كانت مستمدة من تجارب علمية معملية، أو مسوح استقصائية ديموغرافية، أو سجلات مالية وطبية، من ظاهرة شائعة ومؤرقة تتمثل في وجود القيم المفقودة (Missing Values). إن التغافل عن رصد هذه الفجوات البيانية أو التعامل معها بأساليب ارتجالية غير مدروسة يؤدي حتماً إلى استنتاجات مضللة، وتشوهات جوهرية في تقديرات المعالم الإحصائية، وانخفاض حاد في القوة الاختبارية للنماذج الاستدلالية.
تتعامل لغة R Project for Statistical Computing مع القيم المفقودة من خلال بنية برمجية ونظرية فريدة تتمحور حول الرمز الخاص NA (اختصاراً لعبارة Not Available)، والذي صُمم ليعكس حالة عدم التيقن المعرفي والغياب الفعلي للمعلومة دون كسر الاتساق الهيكلي للمتجهات والمصفوفات وإطارات البيانات. لا يقتصر فهم هذا الرمز على إدراك دلالته الرمزية السطحية فحسب، بل يمتد ليشمل فهم آليات توظيفه الداخلي، وكيفية تفاعل العمليات المنطقية والحسابية معه، واستيعاب الفوارق الدقيقة بينه وبين مفاهيم أخرى ملتبسة مثل القيمة غير المعرفة رياضياً NaN، أو الكائن المعدوم برمجياً NULL، أو الكميات اللانهائية Inf. ومن هذا المنطلق، تتطلب الممارسة المنهجية الرصينة في علم البيانات إتقان المهارات التحليلية الكفيلة بتحديد مواقع تلك القيم المفقودة، وتعدادها بدقة، وتوصيف أنماط توزيعها المكاني داخل الهياكل البيانية المختلفة قبل اتخاذ أي قرار منهجي يتعلق بالحذف أو الاستبدال أو التعويض الإحصائي المتقدم.
يهدف هذا الدليل المرجعي الشامل إلى تقديم دراسة موسعة وتطبيقية متعمقة حول كيفية اكتشاف وفحص وحساب القيم المفقودة في لغة R، بدءاً من المبادئ التأسيسية التي تحكم المنطق البولياني والدوال الأساسية المدمجة في النظام القاعدي للغة، مروراً بالوظائف المتطورة التي توفرها منظومة الحزم الحديثة مثل Tidyverse بمكوناتها الرائدة كحزم dplyr وpurrr وtidyr، وصولاً إلى الأساليب البصرية المتقدمة والتشخيص الهيكلي لحالات الفقد المركبة. سيتم استعراض كل مفهوم مدعوماً بالتحليلات العميقة والأمثلة التوضيحية المستفيضة التي تمكن الباحثين والمحللين من ترسيخ أسس راسخة لإدارة جودة البيانات، وضمان أعلى مستويات النزاهة العلمية والدقة الإحصائية في أبحاثهم ومشاريعهم البرمجية.
- 1. مقدمة شاملة حول مشكلة القيم المفقودة (NA) في لغة R وأهمية معالجتها
- 2. المفاهيم الأساسية لتمثيل القيم المفقودة والأنماط الخاصة في R
- 3. الدالة الأساسية is.na(): المبادئ النظرية وكيفية عملها المنطقي
- 4. تحديد مواقع القيم المفقودة في المتجهات والأعمدة باستخدام which()
- 5. حساب إجمالي القيم المفقودة في عمود واحد باستخدام sum() و mean()
- 6. فحص وحساب القيم المفقودة عبر كامل إطار البيانات (Data Frame)
- 7. تطبيق دوال حزمة dplyr للكشف عن القيم المفقودة وإحصائها
- 8. استكشاف وتلخيص القيم المفقودة المتقدم باستخدام حزمة purrr و tidyr
- 9. التمثيل البصري للقيم المفقودة لفهم أنماطها وتوزيعها
- 10. التعامل مع القيم المفقودة في هياكل البيانات المختلفة (المصفوفات، الجداول، والقوائم)
- 11. أمثلة تطبيقية ودراسات حالة عملية خطوة بخطوة في لغة R
- 12. أفضل الممارسات والأخطاء الشائعة عند فحص وحساب القيم المفقودة في R
- خاتمة
- References
1. مقدمة شاملة حول مشكلة القيم المفقودة (NA) في لغة R وأهمية معالجتها
1.1 تعريف القيم المفقودة ودورها في التحليل الإحصائي
تمثل القيم المفقودة في جوهرها انقطاعاً في تدفق المعلومات الملاحظة لوحدة المعاينة أو العنصر التجريبي الخاضع للدراسة؛ حيث يُفترض نظرياً وجود قيمة مقابلة لمتغير ما، إلا أن عملية القياس أو التسجيل فشلت في استحصالها أو توثيقها. في أدبيات التحليل الإحصائي، لا يُنظر إلى الفقدان بوصفه مجرد فراغ عشوائي، بل يُعامل كظاهرة احتمالية بحد ذاتها، صنفها العالم الإحصائي دونالد روبين إلى ثلاثة أطر نظرية رئيسية: الفقدان العشوائي تماماً (Missing Completely at Random – MCAR)، والفقدان العشوائي المشروط (Missing at Random – MAR)، والفقدان غير العشوائي (Missing Not at Random – MNAR). ينطوي كل نمط من هذه الأنماط على افتراضات رياضية محددة تحدد مدى صلاحية التقنيات التحليلية اللاحقة؛ فبينما يمثل الفقدان من نمط MCAR حالة لا تعتمد فيها احتمالية فقدان البيانات على المتغير نفسه أو أي متغير آخر في النموذج، فإن الفقدان من نمط MNAR يرتبط ارتباطاً وثيقاً بالقيمة الفعلية غير المرصودة، مما يولد تحيزاً بنيوياً يصعب تصحيحه بالأساليب التقليدية.
تتعدد الأسباب الكامنة وراء حدوث الفقد في الدراسات التطبيقية؛ ففي المسوح الاجتماعية والديموغرافية، يبرز امتناع المشاركين عن الإجابة على الأسئلة الحساسة المتعلقة بالدخل المالي أو القناعات الشخصية كعامل رئيسي لعدم الاستجابة الجزئية. أما في التجارب المخبرية والعلوم الطبية، فقد تنشأ الفجوات البيانية نتيجة تعطل أجهزة الاستشعار، أو تلف العينات البيولوجية، أو انسحاب المرضى من البروتوكولات العلاجية قبل اكتمال مراحل المتابعة الزمنية. إضافة إلى ذلك، تلعب الأخطاء البشرية أثناء إدخال البيانات وترميزها، والأخطاء البرمجية التي تقع أثناء دمج وتجميع قواعد البيانات غير المتجانسة، دوراً بارزاً في تلويث البيانات بالقيم المفقودة. هذا التنوع في مسببات الفقد يفرض على المحلل التحلي باليقظة المنهجية التامة لتفكيك طبيعة الفقدان قبل الشروع في بناء النماذج الاستنتاجية.
تتجلى التداعيات الإحصائية الخطيرة لإهمال معالجة القيم المفقودة في محورين أساسيين: أولهما انخفاض القوة الإحصائية (Statistical Power) للاختبارات؛ حيث يؤدي استبعاد الحالات التي تحتوي على مفقودات إلى تقليص الحجم الفعلي للعينة، مما يحد من قدرة الباحث على اكتشاف التأثيرات الحقيقية ويزيد من احتمالية ارتكاب خطأ من النوع الثاني. أما المحور الثاني، والأكثر خطورة، فهو توليد تقديرات متحيزة لمعالم المجتمع (Biased Parameter Estimates)؛ إذ إن حذف المشاهدات بطريقة الحذف الكلي للصفوف يؤدي إلى تشويه التوزيعات التكرارية، وتحريف مقاييس النزعة المركزية والتشتت، وإفساد مصفوفات الارتباط والانحدار إذا لم تكن البيانات مفقودة تماماً بنمط عشوائي كامل. وبناءً على ذلك، تبرز مرحلة استكشاف وحساب مواقع ونسب الفقد كخطوة تشخيصية حتمية لا غنى عنها في دورة حياة علم البيانات.
1.2 طبيعة المتغيرات المفقودة في بيئة R البرمجية
تتميز لغة R بتصميم معماري رصين يستوعب الطبيعة التجريدية للقيم المفقودة من خلال تخصيص الرمز المحجوز NA ككائن فريد ذي نمط بيانات مرن، قادر على التوافق مع الأنواع الأساسية للمتجهات دون الإخلال باتساق الذاكرة. على خلاف بعض اللغات البرمجية الأخرى التي تستعيض عن الفقد برموز عددية اصطلاحية مثل -999 أو بسلاسل نصية عشوائية، تتعامل R مع NA كحالة منطقية تمثل انعدام المعلومة. ونتيجة لذلك، فإن أي عملية رياضية أو مقارنة منطقية تُجرى على قيمة مفقودة ستؤدي تلقائياً إلى توليد قيمة مفقودة أخرى، وهو ما يُعرف في علوم الحاسوب بخاصية انتشار القيمة المفقودة (Propagation of Missingness)، والتي تهدف برمجياً إلى تنبيه المحلل إلى أن النتيجة النهائية لا يمكن الجزم بها ما دامت بعض المدخلات مجهولة المصدر.
ينعكس هذا السلوك الرياضي الصارم بوضوح على الدوال الإحصائية القياسية المدمجة في حزمة base R؛ فعلى سبيل المثال، عند تمرير متجه يحتوي على قيم مفقودة إلى دوال حساب المتوسط الحسابي مثل دالة mean، أو الانحراف المعياري عبر دالة sd، أو الوسيط عبر دالة median، فإن المخرج الافتراضي سيكون حتماً NA. يُعد هذا السلوك مقصوداً ومبنياً على فلسفة إحصائية وقائية؛ فالنظام يمتنع عن اتخاذ قرارات افتراضية نيابة عن الباحث، ويلزمه بالتصريح الواضح حول كيفية التعامل مع هذه الفجوات من خلال تضمين المعاملات الخاصة مثل المعامل المنطقي الشهير na.rm = TRUE، والذي يوجه الدالة إلى استبعاد القيم المفقودة مؤقتاً أثناء حساب المعلمة المطلوبة.
انطلاقاً من هذا الواقع البرمجي، تصبح مرحلة الاستكشاف والتعداد الأولي خطوة تمهيدية بالغة الأهمية تسبق أي عملية معالجة أو تعويض إحصائي. إن مجرد اللجوء السريع لحذف المفقودات أو استبدالها بمتوسطات المتغيرات دون تشخيص مسبق قد يخفي وراءه مشكلات هيكلية عميقة في جمع البيانات. يتيح التعداد الدقيق لحجم ونسبة ومواقع القيم المفقودة للمحلل الإجابة عن تساؤلات جوهرية: هل يتركز الفقد في متغيرات معينة دون غيرها؟ هل تتجاوز نسبة الفقد العتبات الحرجة المقبولة أكاديمياً (والتي تتراوح عادة بين 5% إلى 20% بحسب المجال التطبيقي)؟ وهل توجد ارتباطات نمطية بين فقدان قيم معينة وخصائص وحدات المعاينة؟ إن الإجابة المنهجية عن هذه التساؤلات تبدأ من الإلمام بكافة الأدوات التقنية التي تتيحها R لرصد وحساب هذه الظاهرة بدقة متناهية.
2. المفاهيم الأساسية لتمثيل القيم المفقودة والأنماط الخاصة في R
2.1 الفرق بين NA و NaN و NULL و Inf
يقع العديد من المبرمجين والمحللين المبتدئين في خلط مفاهيمي وبرمجي بين مجموعة من الرموز الخاصة التي تستخدمها لغة R لتمثيل الحالات الاستثنائية للبيانات؛ وهي NA و NaN و NULL و Inf. يمثل كل رمز من هذه الرموز حالة دلالية مختلفة تماماً في المنطق البرمجي والرياضي، ويتطلب التعامل معها أساليب فحص متمايزة. كما أسلفنا، يرمز NA إلى القيمة غير المتاحة التي كان ينبغي وجودها ولكنها غائبة لسبب ما، وهو رمز يمتلك طولاً يساوي واحداً داخل المتجه، ويحافظ على وجود الخانة المكانية للعنصر في الهيكل البياني.
في المقابل، يرمز NaN إلى العبارة الرياضية الشهيرة “Not a Number”، وهو مخصص حصرياً لتمثيل نتائج العمليات الحسابية غير المعرفة رياضياً في إطار معيار الأعداد العشرية ذو الفاصلة العائمة (IEEE 754). من الأمثلة الشائعة التي تؤدي إلى توليد NaN محاولة قسمة الصفر على الصفر، أو حساب اللوغاريتم الطبيعي لعدد سالب، أو طرح ما لا نهاية من ما لا نهاية. والجدير بالذكر من الناحية البرمجية أن كل قيمة NaN تُعتبر في نفس الوقت قيمة مفقودة NA بالنسبة لبعض دوال الفحص العامة، ولكن العكس ليس صحيحاً؛ فالقيمة المفقودة العادية ليست بالضرورة ناتجة عن خطأ حسابي أو كمية غير معرفة.
أما الكائن NULL، فهو يمثل المفهوم البرمجي للكائن الخالي أو المعدوم تماماً (Empty Object). على عكس NA، فإن NULL لا يمتلك طولاً (طوله دائماً يساوي صفراً)، ولا يشغل مساحة مكانية كعنصر داخل المتجهات البسيطة؛ فإذا حاولت إدراج NULL داخل متجه عددي، فسيقوم النظام بتجاهله تماماً دون أن يترك أثراً في عدد عناصر المتجه. يُستخدم NULL بصفة أساسية لتفريغ الكائنات، أو لتمثيل الوسائط الافتراضية الفارغة في بناء الدوال البرمجية المخصصة، أو للإشارة إلى القوائم المتداخلة التي لم يتم تخصيص بيانات لها بعد.
أخيراً، يمثل الرمز Inf وسالب اللانهاية -Inf القيم الرياضية اللانهائية الناتجة عن عمليات صالحة حسابياً ولكنها تتجاوز حدود التمثيل الرقمي المتاح في ذاكرة الحاسوب، مثل ناتج قسمة أي عدد موجب أو سالب على الصفر المطلق. لا تُعتبر القيم اللانهائية مفقودة بطبيعتها لأنها تحمل دلالة كمية واضحة (الاتجاه اللانهائي)، إلا أنها تتطلب معالجة خاصة نظراً لأن إدراجها في التحليلات الإحصائية يؤدي إلى إفساد حسابات التباين والمتوسطات بنفس الطريقة التخريبية التي تحدثها القيم المفقودة.
2.2 الأنماط المختلفة للرمز NA وفقاً لنوع البيانات
من الخصائص المعمارية المتقدمة والفريدة في لغة R، والتي قلما يلاحظها المستخدمون العاديون، هي أن الرمز NA ليس مجرد كيان أحادي مطلق، بل هو كائن يتكيف داخلياً مع النمط البرمجي للمتجه الذي يحتويه، وذلك للحفاظ على الخاصية الجوهرية للمتجهات البسيطة في R والمتمثلة في كونها هياكل بيانات متجانسة كلياً (Homogeneous Vectors). من الناحية التأسيسية، يمتلك الرمز NA العام نمطاً منطقياً افتراضياً (Logical)، ولكن عند دمجه داخل متجهات من أنماط أخرى، يتم تحويله ضمنياً إلى أحد الأنماط التخصصية المقابلة لضمان استقرار الذاكرة وتفادي عمليات التحويل القسري غير المقصودة.
تتضمن بيئة R مجموعة من المتغيرات الداخلية المحددة للقيم المفقودة بحسب النمط، وتتمثل في:
- NA_integer_: يمثل القيمة المفقودة المخصصة لمتجهات الأعداد الصحيحة (Integer)، حيث يتم تخزينه في الذاكرة باستخدام أدنى قيمة سالبة ممكنة في تمثيل الأعداد الصحيحة ذات 32 بت.
- NA_real_: يمثل القيمة المفقودة لمتجهات الأعداد الحقيقية ذات الفاصلة العائمة المزدوجة (Double/Numeric)، ويُخزن باستخدام نمط محدد من البتات يتبع معيار الحوسبة العشرية.
- NA_character_: يمثل القيمة المفقودة ضمن متجهات النصوص والسلاسل الحرفية، ويختلف جوهرياً عن النص الفارغ المكتوب بصيغة علامتي تنصيص خاليتين؛ حيث يمثل الأول غياباً تاماً للنص، بينما يمثل الثاني نصاً موجوداً ولكنه ذو طول صفري.
- NA_complex_: يخصص للمتجهات التي تحتوي على أعداد مركبة تضم أجزاء حقيقية وتخيلية.
تكتسب هذه التمايزات أهمية تطبيقية فائقة عند التعامل مع المتغيرات الفئوية أو ما يُعرف في لغة R بعوامل التصنيف Factors. عند وجود قيم مفقودة في متغير تصنيفي، يتعين على المحلل التمييز بين حالتين: اعتبار NA قيمة غير معروفة يجب استبعادها من مستويات العامل (Factor Levels)، أو تحويل NA صراحة إلى مستوى تصنيفي قائم بذاته يحمل اسماً معلناً (كأن يُسمى “غير محدد” أو “مفقود”) باستخدام دوال تخصصية، مما يسمح للنموذج الإحصائي بتقدير أثر غياب الاستجابة كفئة تصنيفية مستقلة بذاتها ومقارنتها مع الفئات المرجعية الأخرى.
3. الدالة الأساسية is.na(): المبادئ النظرية وكيفية عملها المنطقي
3.1 آلية عمل الدالة is.na() على المتجهات
تُعد الدالة is.na() حجر الزاوية والأداة الأكثر أصالة وموثوقية في النظام البيئي للغة R لفحص واكتشاف القيم المفقودة. تقوم هذه الدالة بإجراء تقييم منطقي فوري وموضعي لكل عنصر من عناصر الكائن الممرر إليها، سواء كان ذلك الكائن متجهاً أحادي البعد، أو مصفوفة ثنائية، أو إطار بيانات متعدد المتغيرات. تعمل الدالة وفق مبدأ التقييم الموضعي (Element-wise Evaluation)، حيث تستبدل كل عنصر في الهيكل البياني بقيمة منطقية ثنائية: TRUE إذا كان العنصر المقابل يمثل قيمة مفقودة، أو FALSE إذا كان العنصر يحتوي على قيمة صالحة وملاحظة بالفعل.
تتميز الدالة is.na() بكفاءتها العالية وسرعة تنفيذها الفائقة حتى على مجموعات البيانات الضخمة التي تحتوي على ملايين السجلات؛ وذلك لأنها مكتوبة ومترجمة داخلياً بلغة C المدمجة في نواة محرك R. ينتج عن استدعاء هذه الدالة على متجه ما متجه منطقي مطابق له تماماً في الطول والترتيب. ويتيح هذا المتجه المنطقي للمحلل استخدام قواعد الجبر البولياني لإجراء عمليات الترشيح والاستخلاص والحساب الإحصائي بسهولة بالغة وبأقل استهلاك ممكن لموارد المعالجة المركزية والذاكرة العشوائية.
من أهم المفاهيم البرمجية التي يجب التشديد عليها في هذا السياق هو ضرورة تجنب الخطأ الكارثي الشائع الذي يقع فيه المبتدئون والمتمثل في محاولة فحص الفقد باستخدام معامل المساواة المنطقي المباشر المزدوج. إن محاولة كتابة تعبير منطقي مثل المتجه يساوي NA لن تعيد متجهاً من القيم البوليانية كما يتوهم البعض، بل ستعيد متجهاً كاملاً من القيم المفقودة NA بنفس طول المتجه الأصلي. يعود السبب المنطقي في ذلك إلى المبدأ الذي أشرنا إليه سابقاً: لا يمكن للنظام أن يجزم بما إذا كانت قيمة مجهولة تساوي قيمة مجهولة أخرى، فالمجهول لا يُقارن بالمجهول؛ ولذلك صُممت الدالة is.na() حصرياً لتكون الاستعلام المعتمد للإجابة عن التساؤل: “هل هذه الخانة فارغة أم لا؟”.
3.2 استخدام الدالة complete.cases() كبديل مكمل
بينما تركز الدالة is.na() على الفحص الفردي والتفصيلي لكل عنصر داخل المتغيرات، تقدم لغة R دالة مكملة بالغة الأهمية تُعرف باسم complete.cases()، والتي صُممت خصيصاً للتعامل مع إطارات البيانات والمصفوفات من منظور الحالات الكاملة والصفوف الأفقية. تعمل دالة complete.cases() على تقييم كل سجل أو صف في جدول البيانات ككل؛ حيث تعيد القيمة المنطقية TRUE فقط وفقط إذا كان الصف المعني خالياً تماماً من أي قيمة مفقودة في جميع أعمدته، بينما تعيد القيمة FALSE بمجرد وجود قيمة مفقودة واحدة على الأقل في أي عمود من أعمدة ذلك الصف.
تكتسب هذه الدالة أهمية استثنائية في التحضير للنماذج الإحصائية متعددة المتغيرات، مثل نماذج الانحدار الخطي المتعدد أو التحليل العاملي، والتي تشترط في صيغتها الرياضية الكلاسيكية اكتمال كافة المتغيرات لكل وحدة معاينة. إن استخدام complete.cases() يمنح الباحث تحكماً دقيقاً في تصفية البيانات، حيث يمكن استخدام المتجه المنطقي الناتج عنها لفهرسة إطار البيانات واستخراج مجموعة البيانات النقية التي تخلو من أي تشوهات ناتجة عن الفقدان الجزئي للبيانات عبر المقاطع العرضية المختلفة.
علاوة على ذلك، يتيح الدمج الذكي بين دالة complete.cases() وعامل النفي المنطقي، المتمثل في علامة التعجب !، إمكانية عكس الاستعلام واستخراج كافة الصفوف المعيبة أو غير المكتملة دفعة واحدة. يمثل هذا التعبير العكسي وسيلة تشخيصية رفيعة المستوى تتيح للمحلل عزل السجلات المفقودة وتجميعها في إطار بيانات منفصل لدراسة خصائصها المشتركة، والتحقق مما إذا كان هناك نمط منتظم يجمع بين الحالات التي عجزت أدوات القياس عن استيفاء كامل بياناتها، مما يمهد الطريق لاتخاذ قرارات علمية محكمة بشأن صلاحية استبعادها أو ضرورة تعويضها.
4. تحديد مواقع القيم المفقودة في المتجهات والأعمدة باستخدام which()
4.1 بنية دالة which() وآلية استخراج المؤشرات الموضعية
في كثير من السيناريوهات التحليلية، لا يكفي المحلل أن يعلم بوجود قيم مفقودة كحالة منطقية عامة، بل يحتاج بدقة إلى معرفة أرقام الصفوف والفهارس المكانية (Row Indices) التي تستقر فيها تلك القيم المفقودة داخل المتجه أو العمود البياني. هنا تبرز الدالة الأساسية which() كأداة ربط محورية تقوم بتحويل النتائج المنطقية المجردة إلى أرقام ترتيبية محددة. تستقبل دالة which() متجهاً منطقياً كمدخل أساسي، وتقوم بمسح عناصره تسلسلياً لتعيد متجهاً عددياً يحتوي حصراً على المواقع والفهارس التي كانت قيمتها المنطقية TRUE، مع إغفال تام لجميع المواقع التي احتوت على FALSE أو NA.
عند دمج دالة which() مع الدالة الاستكشافية is.na() في صيغة برمجية واحدة تطبق على عمود محدد داخل إطار البيانات، يتولد استعلام فائق الفعالية والدقة. يُفصح المخرج الناتج عن هذه العملية مباشرة عن أرقام الأسطر التي وقع فيها الفقد في ذلك المتغير. تتيح هذه المؤشرات المكانية للباحث الرجوع المباشر إلى استمارات الاستبيان الأصلية، أو السجلات الورقية، أو ملفات السيرفر الخام للتحقق من سبب الفقد في تلك الحالات المحددة، ومعرفة ما إذا كان الفقد ناتجاً عن سهو في عملية إدخال البيانات يمكن تصحيحه يدوياً ومطابقته مع المصدر الأصلي.
تتميز هذه التقنية بالمرونة والسرعة التوافقية العالية؛ إذ إن متجهات الفهارس المستخرجة يمكن تخزينها في متغيرات مستقلة واستخدامها لاحقاً لإجراء عمليات الفهرسة الجزئية وتعديل القيم مباشرة داخل بيئة R. كما أن قراءة وتفسير المخرجات الناتجة عن which(is.na(متغير)) يتسم بالبساطة المباشرة، مما يجعله خطوة تفتيشية قياسية في كافة البرمجيات النصية المخصصة لتنظيف وتدقيق البيانات الخام قبل اعتمادها في خطوط الإنتاج والتحليل المتقدم.
4.2 استخراج الحالات المفقودة متعددة الشروط
تتجاوز الاحتياجات التحليلية المتقدمة مجرد البحث الأحادي البسيط، لتصل إلى ضرورة تقصي الفقدان المشروط بروابط منطقية متعددة تتفاعل عبر أعمدة مختلفة. تتيح لغة R استخدام معاملات الربط المنطقي الموجهة للمتجهات، مثل معامل الربط المنطقي “و” المتمثل في الرمز & ومعامل الربط المنطقي “أو” المتمثل في الرمز |، لبناء استعلامات معقدة يتم تمريرها إلى دالة which() لحصر وتحديد المؤشرات الموضعية للبيانات بدقة متناهية وفق سياقات متعددة الأبعاد.
يمكن للمحلل، على سبيل المثال، استخراج أرقام السجلات التي تعاني من فقدان في متغير الاستجابة الرئيسي بشرط أن تنتمي وحدة المعاينة إلى فئة عمرية محددة، أو تتبع مجموعة تجريبية معينة دون غيرها. يُمكن صياغة هذه الاستعلامات المركبة من خلال الجمع بين فحص الفقد لدالة is.na() ومقارنات الشروط الفئوية أو العددية الأخرى، مما ينتج عنه متجه منطقي مركب يعكس تقاطع تلك الشروط الصارمة، لتقوم دالة which() بتحويله في النهاية إلى فهارس أسطر محددة تمثل بدقة مجتمع الحالات الخاضعة للفحص الاستثنائي.
تُعد الفهارس المكانية المستخرجة عبر الاستعلامات متعددة الشروط مدخلاً رئيسياً لعمليات المعاينة والتفتيش البصري المباشر؛ حيث يمكن تمرير هذه الفهارس داخل الأقواس المربعة الفهرسية لإطار البيانات لاستعراض تلك الصفوف المحددة بكامل متغيراتها المقابلة. يسهم هذا الاستعراض الموضعي في تزويد الباحث برؤية معمقة حول ما إذا كان الفقدان في متغير معين يترافق دائماً مع قيم شاذة أو سلوكيات معينة في المتغيرات الأخرى، وهو ما يمثل الدعامة الأولى لفهم آليات الفقد واستنتاج ما إذا كانت البيانات تتبع نمط الفقدان العشوائي المشروط (MAR) أو الفقدان غير العشوائي المنحاز (MNAR).
5. حساب إجمالي القيم المفقودة في عمود واحد باستخدام sum() و mean()
5.1 التحويل القسري للمنطق وحساب المجموع عبر sum()
يقودنا الانتقال من مرحلة تحديد الأماكن إلى مرحلة القياس الكمي إلى واحدة من أروع وأبسط الخصائص التصميمية في لغة R؛ وهي خاصية التحويل القسري الضمني للمتغيرات المنطقية (Implicit Coercion). تنص القواعد البنيوية للغة R على أنه عندما يتم تطبيق عملية حسابية أو رياضية على متجه من القيم المنطقية البوليانية، يتم تحويل تلك القيم تلقائياً وبكفاءة رقمية مطلقة إلى قيم عددية مكافئة؛ حيث تأخذ كل قيمة TRUE الرقم الصحيح 1، بينما تأخذ كل قيمة FALSE الرقم الصحيح 0 دون الحاجة إلى تدخل برمجي صريح من المستخدم.
تتجلى عبقرية هذه الخاصية عند دمج الدالة الحسابية التجميعية sum() مع الدالة الاستكشافية is.na() في تعبير واحد يطبق على متغير محدد داخل إطار البيانات. في هذا السياق، تقوم is.na() أولاً بإنتاج سلسلة منطقية تحدد مواضع الفقد بقيم TRUE، ثم تتدخل دالة sum() لتقوم بجمع هذه القيم بعد تحويلها ضمنياً إلى آحاد وأصفار. وتكون النتيجة النهائية لهذا الجمع الرياضي البسيط هي التكرار المطلق الدقيق لإجمالي عدد القيم المفقودة المستقرة داخل ذلك العمود.
يتميز هذا الأسلوب البرمجي بالأناقة الفائقة والاختصار، فضلاً عن تحقيقه لأعلى مستويات الكفاءة الحاسوبية والسرعة في المعالجة؛ حيث يتم تنفيذ عمليتي الفحص والجمع التراكمي على مستوى مسجلات الذاكرة المنخفضة في النظام. إن هذا التركيب البرمجي البسيط يمثل اللبنة الأساسية التي يعتمد عليها محللو البيانات في كتابة تقارير الفحص السريع ومراقبة جودة البيانات الواردة في قواعد البيانات الضخمة التي تتضمن مئات الآلاف من المشاهدات المستمرة دون استهلاك يذكر لموارد المعالج.
5.2 حساب النسبة المئوية للقيم المفقودة عبر mean()
على الرغم من الأهمية الوصفية للتكرار المطلق الذي تقدمه دالة الجمع، فإن التقييم الإحصائي العلمي لجودة المتغيرات يتطلب دائماً صياغة مؤشرات نسبية محايدة لا تتأثر بالحجم الإجمالي للعينة. ومن خلال استثمار نفس المبدأ الرياضي القائم على التحويل القسري للمنطق، تبرز الدالة الإحصائية mean() كوسيلة سحرية وفورية لحساب نسبة الفقد النسبية (Proportion of Missingness) لأي متغير خاضع للدراسة في خطوة برمجية واحدة.
عند تمرير ناتج الدالة is.na() لمتغير ما إلى دالة mean()، تقوم الدالة بحساب المتوسط الحسابي لتلك الآحاد والأصفار؛ وهو ما يعادل رياضياً قسمة مجموع الآحاد (إجمالي القيم المفقودة) على العدد الكلي لعناصر المتجه (حجم العينة الإجمالي بما فيه القيم الصالحة والمفقودة). يعطي هذا الناتج رقماً عشرياً ينحصر بين 0.0 (مما يعني خلو المتغير تماماً من أي فقد) و 1.0 (مما يعني أن المتغير فارغ كلياً بنسبة 100%). ولتحويل هذا الكسر العشري إلى نسبة مئوية مباشرة، يكفي ضرب الناتج في الثابت العددي 100 لتقديمه في التقارير الإحصائية والجداول التنفيذية بصيغة مفهومة وسهلة القراءة لكافة المعنيين.
تكتسب هذه النسبة المئوية أهمية حاسمة في اتخاذ القرارات المنهجية المتعلقة بإدارة البيانات؛ حيث توفر الأدبيات الإحصائية معايير إرشادية واضحة للتعامل مع المتغيرات المفقودة بناءً على نسبة فقدها. فإذا كانت نسبة الفقد ضئيلة جداً (أقل من 5%)، فإن معظم أساليب المعالجة البسيطة أو حتى الاستبعاد لن تؤثر جوهرياً على النتائج. أما إذا تراوحت النسبة بين 5% و 20%، فإن الموقف يستدعي بالضرورة اللجوء إلى خوارزميات التعويض الإحصائي المتعدد (Multiple Imputation). وفي حال تجاوزت النسبة حاجز 40% أو 50%، فإن المتغير يدخل في النطاق الحرج الذي قد يدفع الباحث إلى استبعاده كلياً من التحليل لتفادي إدخال كميات هائلة من عدم التيقن والضوضاء الاصطناعية في النماذج التنبؤية.
6. فحص وحساب القيم المفقودة عبر كامل إطار البيانات (Data Frame)
6.1 حساب الفقد لكل الأعمدة باستخدام colSums() و colMeans()
عند الانتقال من معالجة الأعمدة الفردية إلى تقييم إطار البيانات المتكامل ككتلة بنيوية واحدة، يحتاج المحلل إلى أدوات تتيح له الحصول على نظرة بانورامية شاملة تلخص واقع الفقدان عبر كافة المتغيرات في خطوة واحدة ودون الحاجة إلى كتابة حلقات تكرارية معقدة وبطيئة. توفر لغة R الأساسية دالتين تجميعيتين عاليتي الأداء مخصصتين للتعامل مع المصفوفات والجداول؛ وهما الدالة colSums() والدالة colMeans().
عند تمرير التعبير المنطقي الشامل is.na(df)—حيث يمثل df إطار البيانات المستهدف—إلى دالة colSums()، يقوم النظام أولاً بتوليد مصفوفة منطقية تطابق إطار البيانات في الأبعاد، ثم تطبق دالة colSums() عملية الجمع العمودي المتوازي عبر كافة الأعمدة. ينتج عن ذلك متجه رقمي مسمى (Named Numeric Vector)، يحمل كل عنصر فيه اسم العمود المقابل في إطار البيانات وقيمته تمثل العدد الإجمالي الدقيق للمشاهدات المفقودة في ذلك العمود. وبالمثل، يؤدي استخدام دالة colMeans(is.na(df)) * 100 إلى استخراج متجه فوري يحمل النسب المئوية الدقيقة للفقد في كل متغير على حدة وبسرعة حاسوبية مذهلة.
لتسهيل قراءة هذه المخرجات ومشاركتها مع فرق العمل البحثية، يُفضل دائماً تحويل المتجهات الناتجة إلى إطار بيانات منظم وتنسيقه من خلال ترتيب الأعمدة تنازلياً بحسب شدة الفقد باستخدام دالة الترتيب sort() أو order(). يتيح هذا العرض الهيكلي لمدير المشروع اكتشاف المتغيرات الأكثر هشاشة في قاعدة البيانات فورياً، ووضع خطة عمل واضحة المعالم تحدد أولويات المعالجة والتنظيف للمتغيرات قبل الولوج في مراحل النمذجة الإحصائية المتقدمة.
6.2 حساب الفقد لكل الصفوف والحالات باستخدام rowSums()
في مقابل فحص الأعمدة الذي يركز على المتغيرات وخصائص أدوات القياس، يبرز فحص الصفوف كأداة تشخيصية تركز على وحدات المعاينة (Subjects/Observations)، مثل المشاركين في التجارب السريرية أو الأفراد المستجيبين في استطلاعات الرأي. تتيح الدالة المدمجة rowSums()، عند تطبيقها على المصفوفة المنطقية is.na(df)، حساب إجمالي عدد المتغيرات المفقودة لكل صف أو حالة في مجموعة البيانات على حدة وبصورة مستقلة.
يسهم هذا التحليل الأفقي في الكشف عن السجلات المعيبة التي تعاني من تراكم حاد في الفقد؛ فإذا كان لدينا استبيان يحتوي على ثلاثين سؤالاً، وأظهر تطبيق rowSums() أن أحد المشاركين لديه 28 إجابة مفقودة، فإن هذا السجل لا يمثل سوى عبء إحصائي وضوضاء تشوش دقة النتائج. يتيح المتجه الناتج عن rowSums() بناء معايير استبعاد منهجية واضحة وموضوعية؛ كأن يقرر الباحث استبعاد أي حالة يتجاوز فيها عدد المتغيرات المفقودة عتبة معينة (مثلاً فقدان أكثر من 50% من إجمالي متغيرات الدراسة لكل فرد).
علاوة على ذلك، يمكن استخدام المخرجات العددية لـ rowSums() في تصنيف وفرز أفراد العينة إلى مجموعات متجانسة وفق درجة اكتمال استجاباتهم؛ مما يساعد في إجراء دراسات مقارنة معمقة تبحث في الفروق الجوهرية بين الأفراد متكاملي الاستجابة والأفراد الذين يعانون من تكرار عدم الإجابة. يضمن هذا الإجراء المنهجي التحقق من خلو عينة الدراسة من التحيزات الديموغرافية الناتجة عن تسرب أو انسحاب فئات محددة من المشاركين، وهو ما يرفع من موثوقية الصدق الداخلي والخارجي للبحث.
6.3 استخدام عائلة دوال apply و sapply
تمثل عائلة دوال apply في لغة R حجر الزاوية في البرمجة الوظيفية (Functional Programming)، وتوفر مرونة استثنائية تتجاوز القدرات الافتراضية للدوال المباشرة. عند الرغبة في فحص القيم المفقودة مع تطبيق عمليات تحويل نوعية أو شروط تخصيص متقدمة على إطارات البيانات غير المتجانسة، تبرز دالتا sapply() و lapply() كخيارات برمجية عالية القوة والبيان.
يمكن توظيف دالة sapply() لتمرير دالة مجهولة الاسم (Anonymous Function) عبر كل عمود من أعمدة إطار البيانات لحساب إجمالي المفقودات أو استخراج قائمة مركبة تضم التكرار والنسبة معاً في مخرج واحد مبسط. على الرغم من أن دالة colSums() تتفوق من ناحية السرعة البحتة على المصفوفات المتجانسة، فإن عائلة apply تتفوق ببراعة عندما تشتمل قاعدة البيانات على أعمدة ذات أنواع معقدة، مثل الأعمدة المكونة من تواريخ زمنية، أو القوائم المتداخلة، أو المتغيرات النصية التي تحتاج إلى تنظيف أولي لتوحيد صيغ الفقد قبل تعدادها.
تسمح هذه المرونة الوظيفية للمحلل ببناء دوال تدقيق مخصصة، كأن تقوم الدالة بفحص عدد القيم المفقودة الصريحة NA بالإضافة إلى حصر السلاسل النصية الفارغة التي قد لا تصنفها الدوال القياسية تلقائياً كقيم مفقودة. يعزز هذا النهج من شمولية منظومة التدقيق وجودة المعالجة القبلية للبيانات، ويمنح المبرمج تحكماً كاملاً في صياغة قواعد الجودة بما يتلاءم مع الطبيعة المعقدة للبيانات الواقعية.
7. تطبيق دوال حزمة dplyr للكشف عن القيم المفقودة وإحصائها
7.1 استخدام summarise() و across() للإحصاء المجمع
أحدثت منظومة حزم Tidyverse، وبشكل خاص حزمة dplyr الرائدة، ثورة مفاهيمية في كيفية معالجة وإدارة البيانات في لغة R من خلال تقديم بنية برمجية ترتكز على سهولة القراءة والتعبير المباشر عن العمليات التحليلية المعقدة. وتعتمد هذه المنظومة على مفهوم أنابيب المعالجة (Pipes)، سواء باستخدام المعامل الكلاسيكي للحزمة أو المعامل الأصلي المدمج في إصدارات R الحديثة، لربط الدوال في تدفق منطقي متسلسل يسهل تتبعه وتطويره.
لإجراء إحصاء شامل ومجمع للقيم المفقودة عبر كافة أعمدة إطار البيانات بأسلوب منسق، يُستخدم الدمج القوي بين الدالة التلخيصية summarise() والدالة الموجهة للأعمدة across(). يتيح التعبير across(everything(), ~sum(is.na(.))) توجيه حزمة dplyr لفحص كل عمود دون استثناء، وتطبيق دالة حساب الفقد عليه بصورة متزامنة. ينتج عن هذا التعبير جدول تلخيصي أنيق من نوع Tibble، يتوافق كلياً مع مبادئ البيانات المرتبة (Tidy Data)، حيث يمثل كل عمود فيه متغيراً أصلياً وتحتوي خانته الوحيدة على إجمالي عدد القيم المفقودة المسجلة فيه.
تتجلى قوة هذا الأسلوب في إمكانية تمرير دوال متعددة في آن واحد داخل الدالة across()؛ حيث يمكن للمحلل تمرير قائمة تحوي دالتي الجمع والمتوسط معاً لحساب العدد الإجمالي والنسبة المئوية للفقد لكل عمود في خطوة برمجية واحدة متكاملة. يضمن هذا النهج توليد جداول تلخيصية غنية ومصممة بأعلى معايير التنسيق البياني الحديث، مما يختصر عشرات الأسطر من الأكواد الكلاسيكية ويقلل من احتمالية ارتكاب الأخطاء البرمجية أثناء كتابة البرامج النصية المعقدة.
7.2 حساب القيم المفقودة بحسب المجموعات باستخدام group_by()
في التحليلات الميدانية المتقدمة، نادراً ما يكون معدل الفقدان متجانساً عبر كافة الفئات السكانية أو المجموعات التجريبية؛ فغالباً ما تظهر البيانات تبايناً ملحوظاً في معدلات عدم الاستجابة بين الذكور والإناث، أو بين المناطق الجغرافية المختلفة، أو بين المجموعات العلاجية ومجموعات الشاهد (Control Groups). هنا تظهر الأهمية البالغة للدمج بين الدالة الشهيرة group_by() والدوال التلخيصية لحزمة dplyr.
يتيح تقسيم البيانات بواسطة group_by() بناءً على متغير تصنيفي، ثم تطبيق عمليات إحصاء الفقد عبر summarise()، استخراج جدول مقارنة تفصيلي يوضح عدد ونسبة المفقودات في المتغيرات التابعة لكل فئة تصنيفية على حدة. يُعد هذا الكشف الإحصائي المقسم أداة محورية لاكتشاف الفقد المنحاز (Biased Missingness)؛ فإذا اتضح أن الفقد يتركز بنسبة 80% لدى مجموعة تجريبية تخضع لجرعة دوائية معينة بينما ينعدم لدى مجموعة الشاهد، فإن هذا الفقد يحمل دلالة جوهرية قد تشير إلى حدوث آثار جانبية حادة دفعت المرضى للانسحاب، وهو ما يحول الفقد من مجرد مشكلة تقنية إلى نتيجة علمية بالغة الأهمية يجب توثيقها ومناقشتها في التقرير النهائي.
توفر هذه المقاربات التحليلية المجمعة قاعدة متينة للتحقق التجريبي من صحة افتراضات آليات الفقد (MCAR مقابل MAR)؛ حيث إن الارتباط الإحصائي القوي بين معدل الفقد ومتغيرات التصنيف الديموغرافية أو التجريبية ينفي تماماً فرضية الفقدان العشوائي المطلق، ويفرض على الباحث استخدام نماذج تعويضية مشروطة تراعي الفروق البنيوية بين تلك المجموعات الفرعية لضمان سلامة النماذج التنبؤية اللاحقة.
7.3 تصفية واختيار الحالات المفقودة باستخدام filter()
تمثل عملية عزل السجلات المفقودة خطوة أساسية لفحصها واستكشاف ملابسات حدوثها. وتوفر حزمة dplyr، من خلال دالتها المحورية filter() المدعومة بالمساعدات المتقدمة مثل if_any() و if_all()، مرونة استثنائية في تصفية الصفوف بناءً على شروط الفقد المعقدة دون الحاجة إلى اللجوء لمعاملات الفهرسة المصفوفية التقليدية.
باستخدام التعبير الذكي filter(if_any(everything(), is.na))، يمكن استخلاص وتصفية كافة الصفوف التي تحتوي على قيمة مفقودة واحدة على الأقل في أي عمود من أعمدتها، مما يسمح بإنشاء إطار بيانات فرعي يضم حصراً المشاهدات غير المكتملة لمعاينتها. وعلى الجانب الآخر، يتيح استخدام التعبير filter(if_all(everything(), is.na)) تحديد وعزل الصفوف الفارغة بالكامل؛ وهي تلك السجلات الزائدة التي تتولد أحياناً نتيجة أخطاء أثناء استيراد ملفات الإكسل أو قواعد البيانات، والتي تحتوي على فراغ تام في كافة الحقول وتتطلب الحذف الفوري لتنظيف الجدول البياني.
تتميز أساليب التصفية المعتمدة على dplyr بوضوحها الدلالي وتوافقها التام مع خطوط الإنتاج والتحليل الحديثة في R. كما أنها تتكامل بسلاسة مع أدوات الحفظ والتصدير، مما يتيح للباحث عزل الحالات غير المكتملة وتصديرها إلى ملفات تدقيق مستقلة لتقديمها لفرق جمع البيانات الميدانية، مع الإبقاء على تدفق البيانات الرئيسي مستمراً ونقياً داخل البيئة البرمجية دون انقطاع.
8. استكشاف وتلخيص القيم المفقودة المتقدم باستخدام حزمة purrr و tidyr
8.1 تطبيق دالة map_df() لاستخراج تقارير هيكلية
تقدم حزمة purrr، وهي الذراع التنفيذي للبرمجة الوظيفية داخل منظومة Tidyverse، أدوات فائقة القوة لمعالجة واستكشاف هياكل البيانات المعقدة والمتنوعة. تبرز دالة map_df() كواحدة من أكثر الدوال كفاءة في استخلاص تقارير هيكلية شاملة تلخص واقع القيم المفقودة لكل عمود داخل إطار البيانات وإرجاع المخرجات مباشرة في صورة جدول بيانات متكامل ومنظم بدلاً من القوائم المتشعبة.
يتيح تطبيق دالة map_df() كتابة دوال مخصصة ومضمنة تقوم بحساب حزمة من المؤشرات الإحصائية لكل متغير في آن واحد؛ مثل حساب التكرار المطلق للفقد، وحساب النسبة المئوية الدقيقة، والتعرف على النمط البرمجي للمتغير الأصلي (نوع البيانات: عددي، نصي، عاملي). يتم تجميع هذه المعلومات بصورة تلقائية في صفوف متتالية تقابل أعمدة البيانات الأصلية، مما يوفر تقريراً تدقيقياً فائق التفصيل والوضوح يمكن تصديره كملف تقييم أولي لجودة قاعدة البيانات قبل بدء مرحلة التحليل الاستدلالي.
تتفوق حزمة purrr بشكل خاص عند التعامل مع هياكل البيانات غير النمطية، مثل القوائم المتداخلة أو مجموعات البيانات الضخمة التي تحتوي على مئات المتغيرات ذات الخصائص المتباينة. تضمن هذه المنظومة الوظيفية تجنب الأخطاء الشائعة المرتبطة بتوافق أبعاد المصفوفات وتغير أنماط المخرجات، وتوفر للمحلل بيئة برمجية متماسكة وقابلة للتطوير وبناء حزم العمل والتحليلات الآلية المؤتمتة بكفاءة عالية.
8.2 إعادة تشكيل البيانات باستخدام pivot_longer() للتحليل التجميعي
تعتبر حزمة tidyr الأداة المعيارية الأولى لإعادة هيكلة وتشكيل البيانات في لغة R لتتوافق مع معايير البيانات المرتبة. ومن بين دوالها المركزية، تبرز دالة pivot_longer() التي تتيح تحويل إطار البيانات من الشكل العريض (Wide Format)—حيث تنتشر المتغيرات في أعمدة متعددة—إلى الشكل الطويل (Long Format)، حيث يتم تكديس أسماء المتغيرات في عمود مفتاحي واحد وتوضع القيم المقابلة لها في عمود قيم تالٍ.
يفتح هذا التحويل الهيكلي آفاقاً تحليلية رحبة لدراسة القيم المفقودة؛ إذ يتيح بعد تحويل البيانات إلى الشكل الطويل تطبيق عمليات الفحص والاستكشاف الموحدة على عمود القيم المفرد، ثم تجميع النتائج وتصنيفها بسهولة تامة باستخدام دوال التجميع والعد التقليدية. يمكن للمحلل دراسة توزيع الفقد عبر تصنيفات المتغيرات، وحساب تكرارات وأنماط الفقد المشترك بين مختلف حقول البيانات في خطوة تجميعية واحدة ذات كفاءة معمارية عالية.
بالإضافة إلى ذلك، يُعد التحويل إلى الشكل الطويل عبر pivot_longer() الخطوة التحضيرية الإلزامية لتجهيز مصفوفات الفقد لعمليات التمثيل البياني المتقدم والتفاعلي باستخدام حزم الرسوميات؛ حيث تتطلب معظم أدوات الرسم الحديثة في R استقبال البيانات في صورة جداول طولية مرتبة، مما يسهل ربط المتغيرات بالخصائص البصرية المختلفة مثل الألوان والشبكات التفاعلية واستخراج لوحات القياس التحليلية بجودة استثنائية.
9. التمثيل البصري للقيم المفقودة لفهم أنماطها وتوزيعها
9.1 استخدام حزمة naniar للرسم البياني التفاعلي والوصفي
يمثل التمثيل البصري أداة استكشافية لا غنى عنها لفهم الطبيعة الخفية للبيانات المفقودة، حيث تعجز الجداول التلخيصية الرقمية أحياناً عن إبراز الأنماط المكانية والتكتلات المترابطة للفقد عبر السجلات. وفي هذا الإطار، تبرز حزمة naniar المتخصصة كواحدة من أحدث وأرقى الحزم البرمجية المصممة وفق فلسفة ggplot2 للتعامل الشامل والبصري مع القيم المفقودة واستكشاف أنماطها بدقة استثنائية.
تقدم حزمة naniar مجموعة من الدوال البصرية المتفوقة؛ من أبرزها دالة vis_miss()، والتي تقوم بإنشاء خريطة حرارية شاملة لكامل إطار البيانات، يمثل فيها المحور الأفقي المتغيرات والمحور الرأسي أرقام الصفوف والمشاهدات. يتم تلوين الخانات المكتملة بلون موحد والخانات المفقودة بلون متباين، مع إبراز النسب المئوية العامة للفقد في كل عمود وفي إجمالي الجدول. تتيح هذه الخريطة البصرية للمحلل التقاط الفجوات الهيكلية فوراً؛ مثل اكتشاف وجود قطاع كامل من المشاركين تم إغفال تسجيل استجاباتهم في منتصف الدراسة، أو ملاحظة توقف أحد أجهزة الاستشعار عن التسجيل عند نقطة زمنية محددة.
وعلاوة على ذلك، توفر الحزمة دالة متقدمة للغاية تُعرف باسم gg_miss_upset()، والتي تطبق مخططات التقاطع المركبة (UpSet Plots) لتحليل وفحص التوليفات المشتركة للفقد بين المتغيرات المتعددة. تكشف هذه المخططات البصرية المعقدة بدقة عن مجموعات المتغيرات التي تفقد قيمها معاً وبشكل متزامن في نفس السجلات؛ مما يقدم دليلاً إحصائياً وبصرياً حاسماً حول وجود آليات فقدان بنيوية مشتركة تربط بين متغيرات معينة وتستدعي معالجة جماعية مخصصة بدلاً من التعامل الفردي المعزول.
9.2 التمثيل البصري باستخدام حزم VIM و mice
إلى جانب حزمة naniar، يحظى التحليل البصري للبيانات المفقودة في R بدعم تاريخي وأكاديمي عريق من حزمتين رائدتين هما حزمة VIM (Visualization and Imputation of Missing Values) وحزمة mice (Multivariate Imputation by Chained Equations). تقدم هاتان الحزمتان أدوات تشخيصية متقدمة تربط بين الفحص البصري الدقيق والتمهيد الرياضي لعمليات التعويض الإحصائي المتعدد.
توفر حزمة VIM الدالة الشهيرة aggr()، والتي تقوم بتوليد رسم بياني مزدوج فائق الدقة؛ يتكون جانبه الأيسر من مخطط أعمدة يوضح التكرار والنسبة المئوية للفقد في كل متغير على حدة، بينما يعرض جانبه الأيمن شبكة تقاطعات بصرية توضح كافة أنماط التواجد والغياب المتزامنة بين المتغيرات المختلفة مع بيان تكرار كل نمط منها في قاعدة البيانات. يسهم هذا التمثيل في منح الباحث نظرة فورية ومزدوجة تجمع بين الإحصاء الأحادي والإحصاء المتعدد للأبعاد في لوحة رسم موحدة ومعدة للنشر الأكاديمي المباشر.
من جانبها، تقدم حزمة mice الدالة المحورية md.pattern()، والتي تستعرض مصفوفة أنماط الفقدان بصورة تجمع بين الجدول الرقمي والرسم البياني الهيكلي. تتيح هذه الدالة تصنيف وتتبع ما إذا كان الفقد يتبع نمطاً رتيباً (Monotone Missing Pattern)—حيث يترتب الفقد تسلسلياً بحيث إذا فقدت قيمة في متغير ما فُقدت بالضرورة كافة المتغيرات التالية لها، كما هو شائع في الدراسات التتبعية الطولية عند تسرب المرضى—أو نمطاً غير رتيب (Non-monotone Missing Pattern) تتناثر فيه الفجوات عشوائياً عبر المتغيرات. يُعد تحديد رتابة الفقد شرطاً تقنياً حاسماً لاختيار الخوارزمية الرياضية المناسبة لإجراء التعويض الإحصائي المتعدد، سواء بالاعتماد على الانحدار التسلسلي الخطي أو عبر خوارزمية المعادلات المقيدة المتسلسلة المتقدمة.
10. التعامل مع القيم المفقودة في هياكل البيانات المختلفة (المصفوفات، الجداول، والقوائم)
10.1 البحث عن المفقودات في المصفوفات (Matrices)
على الرغم من أن إطارات البيانات (Data Frames) تمثل الهيكل الأكثر شيوعاً في التعامل اليومي مع البيانات، فإن المصفوفات العددية Matrices تمثل البنية الأساسية في الحسابات الرياضية المتقدمة، وخوارزميات تعلم الآلة، والتحليلات الجبرية في لغة R. يمتلك فحص القيم المفقودة داخل المصفوفات خصوصية برمجية ترتبط بالحاجة إلى استخراج الإحداثيات الثنائية للأبعاد (الصف والعمود معاً) لتحديد موقع الخلية المصابة بدقة متناهية.
لتحقيق ذلك، تتيح الدالة المدمجة which() ميزة استثنائية عند تزويدها بالمعامل الإضافي المخصص للأبعاد arr.ind = TRUE عند تطبيقها على المصفوفة المفحوصة بواسطة is.na(mat). بدلاً من إرجاع متجه أحادي بسيط للأرقام التسلسلية، تقوم الدالة في هذه الحالة بتوليد مصفوفة فهرسية ذات عمودين رئيسيين؛ يحمل العمود الأول رقم الصف (Row Index) بينما يحمل العمود الثاني رقم العمود (Column Index) لكل خلية تحتوي على قيمة مفقودة. يتيح هذا التمثيل الإحداثي الدقيق للمحلل استهداف ومعالجة الخلايا المفقودة بصورة جبرية مباشرة دون الحاجة لتحويل المصفوفة إلى إطار بيانات أو إجراء مسح تكراري بطيء للأبعاد.
تتفوق المصفوفات الرياضية بشكل جوهري على إطارات البيانات في سرعة المعالجة واستهلاك الذاكرة عند تطبيق دوال الفحص التجميعية؛ نظراً لأن المصفوفات تمثل كتلة ذاكرية متجانسة كلياً ومخزنة بصفة خطية متتابعة في الذاكرة العشوائية. وعليه، فإن العمليات الجبرية للتحقق من الفقد على المصفوفات الكبيرة، والتي تتضمن ملايين العناصر الرقمية، تتم في أجزاء ضئيلة من الثانية، مما يجعلها الهيكل المفضل لبناء الخوارزميات الإحصائية الحسابية المكثفة والتعامل مع بيانات المقاييس المجهرية والصور الرقمية.
10.2 فحص القيم المفقودة في القوائم (Lists) والكائنات المتداخلة
تمثل القوائم Lists الهيكل البياني الأكثر مرونة وتعقيداً في لغة R؛ حيث تتيح القائمة الواحدة تخزين عناصر غير متجانسة تضم متجهات ذات أطوال مختلفة، ومصفوفات، ونماذج إحصائية، وقوائم فرعية متداخلة داخل بعضها البعض بعمق غير محدود. يفرض هذا التباين الهيكلي تحديات برمجية فريدة عند الرغبة في تتبع وحساب القيم المفقودة المستقرة في المستويات الفرعية لتلك الهياكل المتشعبة.
للتعامل مع هذه القوائم المعقدة، يتم اللجوء إلى الدالة التكرارية المتقدمة rapply() (وهي اختصار لعبارة Recursive Apply) أو الاستعانة بدوال حزمة purrr مثل modify_depth(). تتيح دالة rapply() النزول الذاتي والتلقائي عبر كافة مستويات وتفرعات القائمة المتداخلة، وتطبيق الدالة is.na() على كل متجه أولي مستقر في أعماق القائمة، ومن ثم تجميع وإرجاع إجمالي عدد المفقودات في صورة متجه مسطح أو قائمة تلخيصية مماثلة في البنية للشجرة الأصلية.
تكتسب هذه التقنيات الوظيفية المتقدمة أهمية قصوى في معالجة البيانات الحديثة المستخرجة من واجهات برمجة التطبيقات (APIs) أو ملفات تنسيق JSON، والتي غالباً ما يتم استيرادها إلى بيئة R في صورة قوائم متداخلة أو ما يُعرف بأعمدة القوائم (List-columns) داخل جداول Tibble الحديثة. يضمن التمكن من هذه الأدوات قدرة المحلل على تنظيف وتدقيق البيانات المعقدة في موضعها الأصلي قبل الشروع في فك ضغطها وتسطيحها إلى جداول مستقيمة، مما يمنع حدوث أخطاء الانهيار البرمجي أثناء مراحل التحويل الهيكلي اللاحقة.
11. أمثلة تطبيقية ودراسات حالة عملية خطوة بخطوة في لغة R
11.1 دراسة حالة 1: تحليل بيانات رياضية وإحصاءات الأداء (مثال تفصيلي)
لتجسيد المفاهيم السابقة في سياق تطبيقي مباشر، نفترض أننا بصدد تحليل قاعدة بيانات رياضية توثق إحصاءات الأداء لمجموعة من لاعبي كرة السلة في مسابقة دوري المحترفين. يتكون إطار البيانات الخاضع للدراسة من أربعة متغيرات رئيسية: اسم الفريق (Team)، والنقاط المسجلة (Points)، والتمريرات الحاسمة (Assists)، والمتابعات الدفاعية والهجومية (Rebounds). سنقوم ببناء هذا الإطار ومحاكاة وجود قيم مفقودة في مواضع مختلفة لتطبيق كافة خطوات الكشف والحساب خطوة بخطوة.
في البداية، يتم إنشاء إطار البيانات الافتراضي وتهيئته في بيئة R ليتضمن قيماً صالحة ومجموعة متفرقة من القيم المفقودة الموزعة بين المتغيرات العددية؛ كأن يتضمن عمود التمريرات الحاسمة (Assists) قيماً مفقودة في الصفوف الثاني والخامس والسابع، بينما يحتوي عمود المتابعات (Rebounds) على قيم مفقودة في الصفين الخامس والثامن. لتنفيذ التدقيق الموضعي على عمود التمريرات الحاسمة، نبدأ بتطبيق التركيب البرمجي which(is.na(df$Assists)). يعيد هذا الأمر فورياً المتجه العددي الذي يضم الأرقام (2، 5، 7)، مما يحدد بدقة متناهية أرقام السجلات التي تحتاج إلى مراجعة وتدقيق لحصر غياب بيانات التمريرات للاعبين المعنيين.
في الخطوة التالية، نطبق الدوال التجميعية لتقدير الحجم الكمي للفقد في هذا العمود الرياضي؛ حيث يؤدي استدعاء الأمر sum(is.na(df$Assists)) إلى استخراج الرقم 3، وهو العدد المطلق للتمريرات المفقودة. بينما يعيد الأمر mean(is.na(df$Assists)) * 100 النسبة المئوية الدقيقة التي توضح أن الفقد يمثل، على سبيل المثال، 30% من إجمالي سجلات العينة الخاضعة للاختبار. يتيح هذا التحليل البسيط والمنهجي لمدير الفريق الرياضي تقييم مدى كفاية البيانات المسجلة عن أداء اللاعبين قبل البدء في اتخاذ قرارات التعاقد أو التقييم الفني المبني على نماذج الكفاءة المتقدمة.
11.2 دراسة حالة 2: مسح استبياني معقد متعدد المتغيرات
تتمثل الحالة التطبيقية الثانية في إجراء تدقيق إحصائي متكامل لمسح استبياني نفسي واجتماعي تم تطبيقه على عينة واسعة من المستجيبين. يتضمن الاستبيان قسماً ديموغرافياً يضم متغيرات العمر، والجنس، ومستوى الدخل، بالإضافة إلى مقياس ليكرت خماسي يتكون من عشرة عناصر تقيس مستوى الرضا الوظيفي والاحتراق النفسي في بيئة العمل. تعاني مثل هذه المسوح عادة من ظاهرة عدم الاستجابة المتفرقة في الأسئلة الحساسة وخاصة ما يتعلق بمستوى الدخل والأسئلة التقويمية للإدارة.
تتضمن الخطة البرمجية لبناء تقرير الفحص الشامل في هذا السيناريو كتابة برنامج نصي متكامل يعتمد على حزمة dplyr ومنظومة Tidyverse. تبدأ الخطوة الأولى بحساب الفقد لكل سؤال ولكل متغير ديموغرافي باستخدام summarise(across(everything(), list(count = ~sum(is.na(.)), pct = ~mean(is.na(.)) * 100)))، مما يولد جدولاً تدقيقياً عريضاً يوضح توزيع الفقد ونسبته المئوية عبر كافة أسئلة المقياس الاستبياني. يكشف هذا التقرير بدقة عن الأسئلة المعيبة التي شهدت عزوفاً جماعياً عن الإجابة بسبب صياغتها الغامضة أو حساسيتها المفرطة.
في الخطوة الثانية، يتم الانتقال إلى الفحص الأفقي لسلوك المستجيبين من خلال حساب إجمالي الأسئلة المتروكة لكل مشارك باستخدام rowSums(is.na(survey_data))، ثم تطبيق دالة التصفية filter() لعزل المشاركين الذين تجاوزت نسبة استجاباتهم المفقودة حاجز 40% من أسئلة الاستبيان تمهيداً لاستبعادهم المنهجي وتوثيق أسباب الاستبعاد في منهجية الدراسة. يختتم البرنامج النصي بإنتاج جدول مقارنة يوضح معدلات الفقد في أسئلة الرضا الوظيفي مصنفة بحسب فئات الجنس والقطاع الوظيفي باستخدام group_by()، للتأكد من خلو البيانات المتبقية من أي تحيز فئوي منظم قبل الشروع في حساب معاملات الصدق والثبات وإجراء التحليل العاملي التوكيدي.
11.3 دراسة حالة 3: فحص بيانات سلاسل زمنية بيئية أو طبية
تتميز بيانات السلاسل الزمنية (Time Series) المستمرة—مثل تسجيلات الانبعاثات الكربونية اليومية لمحطات الرصد البيئي، أو المؤشرات الحيوية المستمرة لمرضى العناية المركزة (مثل تخطيط القلب ومستويات تشبع الأكسجين)—بأهمية الترتيب الزمني الصارم للمشاهدات، حيث يمثل انقطاع البيانات في فترة زمنية معينة تحدياً كبيراً يؤثر على حساب الارتباط الذاتي والتنبؤات المستقبلية للنماذج الزمنية مثل نماذج ARIMA أو نماذج الفضاء الزمني المتطورة.
في هذه الدراسة التطبيقية، نتعامل مع سلسلة زمنية بيئية تسجل تركيزات ملوثات الهواء بالساعات على مدار عام كامل. يؤدي استخدام دالة الفهرسة الموضعية which(is.na(air_pollution$PM25)) إلى استخراج متجهات الأرقام التسلسلية لساعات الانقطاع. ومن خلال حساب الفروق المتتالية بين تلك الفهارس باستخدام دالة الفروق diff()، يستطيع المحلل تصنيف فترات الفقدان إلى: انقطاعات متفرقة ومعزولة (تستمر لساعة واحدة أو ساعتين نتيجة خلل مؤقت في الإرسال)، أو انقطاعات ممتدة وكتلية (تستمر لأيام أو أسابيع نتيجة خروج المحطة عن الخدمة).
يعد هذا التوصيف الهيكلي الدقيق لفترات الانقطاع الخطوة التأسيسية التي تحدد برمجياً نوع المعالجة الزمنية المناسبة للمرحلة اللاحقة؛ فالانقطاعات القصيرة المتفرقة يتم التعامل معها بنجاح عبر خوارزميات الاستيفاء الخطي أو الاستيفاء باستخدام التواءات سبلاين الرياضية (Spline Interpolation)، بينما تتطلب الانقطاعات الممتدة تطبيق نماذج التنبؤ الموسمي المتطورة أو استعارة بيانات المحطات المجاورة لتعويض الفجوات الكبيرة. تضمن هذه المنهجية التطبيقية الدقيقة حماية التحليل الزمني من التشوهات والحفاظ على ديناميكية الظاهرة المدروسة عبر الزمن.
12. أفضل الممارسات والأخطاء الشائعة عند فحص وحساب القيم المفقودة في R
12.1 الأخطاء البرمجية الشائعة وكيفية تجنبها
يقع الكثير من مستخدمي لغة R في مجموعة من العثرات البرمجية المتكررة التي تؤدي إلى توليد نتائج غير دقيقة أو إفساد تدفق المعالجة التحليلية دون إظهار رسائل خطأ واضحة. يأتي في مقدمة هذه الأخطاء، كما شددنا سابقاً، استخدام معامل المقارنة المنطقية المزدوج لفحص الفقد في جمل مثل x == NA؛ حيث يعيد هذا التعبير متجهاً مشوهاً من NA بدلاً من القيم المنطقية الصالحة، ويكمن الحل الوحيد والصحيح دائماً في الاعتماد الحصري على الدالة المعيارية المخصصة is.na(x).
الخطأ الشائع الثاني يتمثل في نسيان أو تجاهل تضمين المعامل الوقائي na.rm = TRUE داخل الدوال التلخيصية الكلاسيكية (مثل mean و sum و sd) عند التعامل مع المتجهات التي تحتوي على بيانات مفقودة؛ مما يؤدي إلى إعادة القيمة NA للمخرج بأكمله وضياع نتيجة الحساب. يجب على المحلل أن يعي دلالة هذا المعامل وأن يستخدمه بوعي بعد أن يكون قد أجرى الفحص الاستكشافي المسبق وتأكد من أن الاستبعاد اللحظي للمفقودات لن يضر بسلامة المؤشر الإحصائي المحسوب.
أما الخطأ البرمجي الثالث، والأكثر خفاءً في مجموعات البيانات الواقعية، فهو الخلط بين السلاسل النصية الفارغة الممثلة بعلامتي تنصيص متلاصقتين “”، أو النصوص الاصطلاحية التي تستخدمها بعض البرمجيات مثل “N/A” أو “None” أو “Missing”، وبين القيمة المفقودة الحقيقية NA. إن الدوال القياسية مثل is.na() ستعتبر تلك السلاسل النصية قيماً صالحة وملاحظة ولن ترصدها كقيم مفقودة. لتصحيح هذا الخطأ، توفر حزمة dplyr الدالة الممتازة na_if()، والتي تتيح استبدال النصوص الاصطلاحية أو القيم العددية الشاذة بالرمز الحقيقي NA في خطوة تنظيف استباقية تضمن انطباق كافة أدوات الفحص والإحصاء اللاحقة عليها بكفاءة تامة.
12.2 أفضل الممارسات المنهجية لإعداد تقارير البيانات المفقودة
تقتضي النزاهة العلمية والاحترافية المهنية في علم البيانات اتباع بروتوكول توثيقي صارم يتعامل مع مرحلة فحص وحساب القيم المفقودة كجزء بنيوي أصيل في مرحلة المعالجة القبلية للبيانات (Data Preprocessing). يجب أن يتضمن أي تقرير إحصائي أو بحث علمي قسماً منهجياً يوثق بوضوح إجمالي عدد ونسب المفقودات في كافة المتغيرات، وتوزيعها المكاني، مع بيان الفحوصات التي أُجريت للتحقق من نمط الفقدان وفرضياته الاحتمالية.
من أفضل الممارسات البرمجية الموصى بها داخل بيئات العمل البرمجية في R بناء دوال فحص قياسية قابلة لإعادة الاستخدام (Reusable Validation Functions) يتم تضمينها في مكتبات العمل الخاصة بالمؤسسة أو حزم المشاريع. تقوم هذه الدوال آلياً باستقبال أي إطار بيانات خام، وإنتاج تقرير تدقيقي متكامل يجمع بين الجداول العددية والرسوم البيانية، وينبه المحلل تلقائياً عبر رسائل تحذيرية إذا تجاوزت نسبة الفقد في أي متغير حداً حرجاً تم ضبطه مسبقاً، مما يضمن اتساق معايير الجودة عبر كافة المشاريع البحثية والتطبيقية.
ختاماً، يجب أن تنعكس نتائج الاستكشاف والحساب على اتخاذ قرارات منهجية مستنيرة ومبررة علمياً تفصل بوضوح بين خياري: الاستبعاد (Deletion) و التعويض (Imputation). فبينما يمكن قبول الحذف الكلي للصفوف في الحالات البسيطة التي تثبت فيها عشوائية الفقد المطلقة مع تدني نسبته (أقل من 5%)، فإن المواقف الأكثر تعقيداً تفرض اللجوء إلى تقنيات التعويض الإحصائي المتقدمة كاستخدام خوارزميات الغابات العشوائية، أو التعويض بالمعادلات المقيدة المتسلسلة عبر حزمة mice، أو النمذجة البيزية الكاملة، بما يضمن الحفاظ على حجم العينة الأصلي، وتفادي تشويه العلاقات البينية، وتحقيق أعلى درجات الدقة والموثوقية في النتائج الإحصائية المستخلصة.
خاتمة
استعرض هذا الدليل المرجعي الشامل الأبعاد النظرية والبرمجية والتطبيقية العميقة للتعامل مع القيم المفقودة (NA) في بيئة الحوسبة الإحصائية R. لقد أوضحنا أن إدارة الفجوات البيانية لا تمثل مجرد مهمة برمجية روتينية تقتصر على حذف الصفوف المعيبة، بل هي عملية منهجية متكاملة تتطلب فهماً عميقاً للأنماط الرياضية للفقد، واستيعاباً للخصائص البنيوية التي تميز لغة R في تخزين وتمثيل الرموز الخاصة مثل NA وNaN وNULL وInf. إن الانطلاق من هذه الأسس النظرية المتينة هو ما يمنح المحلل القدرة على توظيف الدوال الأساسية للنظام بكفاءة وثقة، واستخراج المؤشرات الموضعية الدقيقة، وحساب المقاييس التكرارية والنسبية للفقد بأعلى مستويات الأداء الحاسوبي.
كما بينت المقاربات التحليلية المتقدمة التي استعرضناها عبر منظومة Tidyverse وحزم dplyr وpurrr وtidyr، إلى جانب أدوات التمثيل البصري الاحترافية في حزم naniar وVIM وmice، أن بيئة R توفر ترسانة برمجية متكاملة وقادرة على تحويل تحدي البيانات المفقودة إلى فرصة استكشافية لفهم البنية العميقة للظواهر المدروسة وسلوك وحدات المعاينة. إن الالتزام بأفضل الممارسات المنهجية، وتجنب الأخطاء البرمجية الشائعة، وتوثيق كافة خطوات التشخيص والفحص بدقة متناهية، يمثل الضمانة الحقيقية لحماية الدراسات العلمية والنماذج التنبؤية من التحيزات الهيكلية، وتحقيق أعلى معايير الصدق والدقة والنزاهة الإحصائية في عالم البيانات المعاصر.
References
- Endors, C. K. (2010). Applied missing data analysis. Guilford Press. https://www.guilford.com/books/Applied-Missing-Data-Analysis/Craig-Enders/9781606236390
- Grolemund, G., & Wickham, H. (2017). R for data science: Import, tidy, transform, visualize, and model data. O’Reilly Media. https://r4ds.had.co.nz/
- Kowarik, A., & Templ, M. (2016). Imputation with the R package VIM. Journal of Statistical Software, 74(7), 1–16. https://doi.org/10.18637/jss.v074.i07
- Little, R. J. A., & Rubin, D. B. (2019). Statistical analysis with missing data (3rd ed.). John Wiley & Sons. https://doi.org/10.1002/9781119482260
- R Core Team. (2023). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/
- Tierney, N. J., & Cook, D. (2023). Expanding tidy data principles to facilitate missing data exploration, visualization and assessment of imputations. Journal of Statistical Software, 105(7), 1–31. https://doi.org/10.18637/jss.v105.i07
- van Buuren, S. (2018). Flexible imputation of missing data (2nd ed.). Chapman and Hall/CRC. https://stefvanbuuren.name/fimd/
- van Buuren, S., & Groothuis-Oudshoorn, K. (2011). mice: Multivariate imputation by chained equations in R. Journal of Statistical Software, 45(3), 1–67. https://doi.org/10.18637/jss.v045.i03
- Wickham, H. (2019). Advanced R (2nd ed.). Chapman and Hall/CRC. https://adv-r.hadley.nz/
- Wickham, H., Averick, M., Bryan, J., Chang, W., McGowan, L. D., François, R., Grolemund, G., Hayes, A., Henry, L., Hester, J., Kuhn, M., Pedersen, T. L., Miller, E., Bache, S. M., Müller, K., Ooms, J., Robinson, D., Seidel, D. P., Spinu, V., … Yutani, H. (2019). Welcome to the Tidyverse. Journal of Open Source Software, 4(43), 1686. https://doi.org/10.21105/joss.01686