Data SciencePython Programming

بانداس: كيفية التصفية حسب “لا يحتوي على

دليل أكاديمي مفصل يشرح آليات وتقنيات تصفية واستبعاد السلاسل النصية في مكتبة بانداس (Pandas) بلغة بايثون باستخدام التعبيرات النمطية والمعاملات المنطقية.

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

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

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

تكتسب عمليات “الاستبعاد الشرطي” أو التصفية السلبية (Negative Filtering) — المتمثلة في استعلام “لا يحتوي على” (Not Contains) — أهمية استثنائية تفوق في كثير من الأحيان عمليات التضمين المباشر. فعند تنقية المسوح الاستقصائية، أو معالجة المدونات النصية الضخمة، أو استبعاد السجلات الإعلانية المشبوهة، يصبح تحديد ما يجب إسقاطه من البيانات هو المعيار الحاسم لضمان نزاهة النماذج التنبؤية ودقة التحليلات الاستدلالية. إن الفهم الرياضي والبرمجي لكيفية صياغة هذا الاستبعاد وتطبيقه دون الوقوع في الفخاخ المنطقية أو استنزاف موارد الذاكرة يمثل فارقاً جوهرياً بين التحليل السطحي والهندسة الاحترافية للبيانات.

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

1. مقدمة شاملة لمكتبة بانداس ومفهوم تصفية البيانات النصية

1.1 أهمية تصفية البيانات النصية في علم البيانات وتحليل السلوك

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

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

يشكل مفهوم الاستبعاد الشرطي ركيزة بنيوية في حقول معالجة اللغات الطبيعية (NLP). قبل تدريب نماذج تضمين الكلمات (Word Embeddings) أو النماذج اللغوية الكبيرة (LLMs)، تتطلب مرحلة تجهيز البيانات الأولية (Data Preprocessing) تصفية السجلات التي تحتوي على مصطلحات بذيئة، أو بيانات حساسة تخضع للوائح الخصوصية، أو شيفرات برمجية متداخلة. هنا، لا يكون الهدف مجرد تقليص حجم البيانات، بل رفع جودتها المعرفية وكفاءة تدريب النماذج الرياضية اللاحقة.

1.2 نظرة عامة على هياكل بيانات بانداس والوصول النصي (str accessor)

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

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

يرتبط هذا التصميم بمفهوم الحوسبة المتجهة (Vectorized Operations). في الحوسبة المتجهة، يتم تطبيق العملية الحسابية أو المنطقية على مصفوفة كاملة من البيانات دفعة واحدة على مستوى الذاكرة المنخفضة (Low-level Memory)، متجاوزةً عبء إدارة العمليات في مفسر بايثون (Python Interpreter Overhead). هذا الأسلوب يقلل من زمن المعالجة بشكل كبير، ويسمح لمحللي البيانات بتنفيذ عمليات بحث واستبعاد معقدة على مجموعات بيانات ضخمة في أجزاء من الثانية.

1.3 مقارنة منهجية بين منطق التضمين (Contains) والاستبعاد (Not Contains)

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

يؤثر هذا الاختيار المنهجي تأثيراً مباشراً على حجم العينة ودقتها الإحصائية. عند تطبيق التضمين الصارم، يواجه الباحث خطر الوقوع في “الخطأ من النوع الثاني” (Type II Error)، حيث يتم استبعاد سجلات صالحة وذات صلة فقط لأنها لم تحتوي حرفياً على النمط المحدد. بالمقابل، عند استخدام الاستبعاد الشرطي، يتم الحفاظ على التنوع الطبيعي للبيانات مع إزالة الشوائب المعروفة فقط، مما يقلل من احتمالية التحيز في اختيار العينة (Selection Bias) ويحافظ على التوزيع الإحصائي الأصلي للظاهرة المدروسة.

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

2. الأساس النظري لعمليات التحقق الشرطي والتعامل مع الأقنعة المنطقية

2.1 بناء وفهم الأقنعة المنطقية (Boolean Masking) في بايثون

يُعد القناع المنطقي (Boolean Mask) مفهوماً جوهرياً في معالجة المصفوفات وهياكل البيانات في بيئة بايثون العلمية، وتحديداً في مكتبتي NumPy و Pandas. القناع المنطقي هو عبارة عن مصفوفة أو سلسلة أحادية البعد (Series) تتألف بالكامل من قيم بوليانية ثنائية (True و False)، وتكون متطابقة تماماً في الطول والترتيب مع مؤشر إطار البيانات الأصلي. يتم توليد هذا القناع عندما نقوم بتقييم شرط منطقي معين على كل عنصر من عناصر العمود النصي المستهدف.

تتم عملية الفهرسة المنطقية (Boolean Indexing) بتمرير هذا القناع إلى إطار البيانات باستخدام أقواس الفهرسة المربعة (Square Brackets). يقوم محرك بانداس بفحص كل صف في الجدول؛ فإذا كانت القيمة المقابلة له في القناع هي True، يتم تضمين الصف في الناتج النهائي، وإذا كانت False، يتم استبعاده وإسقاطه. تتيح هذه الآلية إجراء عمليات تصفية عالية الكفاءة دون الحاجة إلى إعادة بناء البيانات أو نسخها يدوياً في هياكل وسيطة.

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

2.2 المنطق البولياني والعمليات الثنائية في بانداس

يخضع التعامل مع الأقنعة المنطقية في بانداس لقواعد الجبر البولياني (Boolean Algebra)، وهو النظام الرياضي الذي يتعامل مع القيم الثنائية من خلال عمليات النفي المنطقي (NOT)، والوصل المنطقي (AND)، والفصل المنطقي (OR). في سياق تصفية البيانات النصية، يتيح النفي المنطقي قلب مخرجات الشرط؛ فالقيم التي تم تقييمها بأنها True تتحول إلى False، والعكس صحيح، وهو الأساس النظري لبناء مرشحات “لا يحتوي على”.

من المهم جداً التمييز بين المعاملات المنطقية القياسية في لغة بايثون (مثل الكلمات المحجوزة and، or، not) والمعاملات الثنائية النقطية (Bitwise Operators) المستخدمة في بانداس وNumPy (وهي &، |، ~). المعاملات القياسية تُقيم الحقيقة المنطقية للكائن ككل ككتلة واحدة (Scalar context)، وبالتالي لا يمكنها تقييم متجهات تحتوي على سلاسل من القيم المنطقية وتؤدي إلى ظهور خطأ نحوي شهير. في المقابل، تقوم معاملات البت بتطبيق العملية المنطقية عنصراً بعنصر (Element-wise) عبر كامل السلسلة، وهو ما يتطلبه تقييم الأقنعة المنطقية.

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

3. استخدام الدالة str.contains مع المقارنة الصريحة بالمساواة الخاطئة

3.1 الصيغة التركيبية للطريقة الأولى (== False)

تتمثل إحدى الطرق المباشرة لإجراء التصفية السلبية في مكتبة بانداس في استدعاء الدالة str.contains() ومقارنة مخرجاتها البوليانية بشكل صريح بالقيمة المنطقية False. تأخذ هذه الصيغة الشكل البرمجي التالي:

df[df['column_name'].str.contains('pattern') == False]

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

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

3.2 تطبيق عملي: استبعاد قيمة نصية مفردة من متغير فئوي

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

لنفرض أن إطار البيانات تم تعريفه على النحو التالي:

  • السجل الأول: أحمد – قسم الهندسة – الملاحظة: “أداء ممتاز ومستمر”
  • السجل الثاني: سارة – قسم العلوم – الملاحظة: “يحتاج تدريب إضافي وتطوير”
  • السجل الثالث: خالد – قسم الهندسة – الملاحظة: “أداء متميز وتفوق ملحوظ”
  • السجل الرابع: مريم – قسم الإدارة – الملاحظة: “يحتاج تدريب مكثف في القيادة”

إذا كان الهدف هو استبعاد الموظفين الذين تحتوي ملاحظاتهم على عبارة “تدريب”، يتم تطبيق الكود التالي:

filtered_df = df[df['الملاحظات'].str.contains('تدريب') == False]

عند تنفيذ هذه العملية، يقوم محرك بانداس باختبار كل صف؛ فيجد أن السجلين الثاني والرابع يحتويان على كلمة “تدريب”، وبالتالي تكون نتيجة الدالة لهما True، وعند مقارنتها بـ == False تصبح النتيجة النهائية False. أما السجلان الأول والثالث، فتكون نتيجة الدالة لهما False، وتتحول بالمقارنة إلى True. ينتج عن ذلك إطار بيانات جديد يحتوي فقط على أحمد وخالد، وتتقلص أبعاد المصفوفة من 4 صفوف إلى صفين فقط.

بعد إتمام عملية التصفية، تظل الفهارس الأصلية (0 و 2) محتفظة بقيمها السابقة، مما قد يسبب فجوات في الترقيم المتسلسل. لذلك، يُعد من أفضل الممارسات المنهجية إعادة تعيين الفهرس باستخدام التابع reset_index(drop=True) لإنتاج مصفوفة مرتبة تسلسلياً تبدأ من الصفر، مما يسهل العمليات التحليلية اللاحقة دون حدوث ارتباك في الفهرسة العددية.

3.3 تحليل القيود والاعتبارات النظرية للمقارنة الصريحة

على الرغم من بساطة أسلوب المقارنة الصريحة بـ == False، إلا أنه ينطوي على قيود منهجية وبرمجية خطيرة تجعل استخدامه غير محبذ في بيئات الإنتاج والتحليلات المعقدة. يكمن الخطر الأكبر في كيفية تعامل هذه الصيغة مع القيم المفقودة (NaN أو None). إذا كان العمود النصي يحتوي على قيم مفقودة، فإن الدالة str.contains() قد تُرجع قيمة NaN لتلك الصفوف. عند مقارنة NaN == False، تكون النتيجة في لغة بايثون هي False دائماً، مما يؤدي إلى استبعاد الصفوف ذات القيم المفقودة تلقائياً دون إدراك الباحث، وهو ما قد يتسبب في فقدان غير مقصود لبيانات حيوية وتشويه حجم العينة الأصلية.

علاوة على ذلك، تواجه هذه الطريقة مشكلات عند التعامل مع الأعمدة ذات الأنواع المختلطة (Mixed Data Types)، مثل الأعمدة التي تجمع بين النصوص والأرقام الصحيحة. في مثل هذه البيئات، قد تفشل المقارنة المباشرة في توفير نتائج منطقية متناسقة، مما يؤدي إلى سلوك غير متوقع للبرنامج وصعوبة في اكتشاف الأخطاء الخفية (Silent Bugs).

من منظور هندسة البرمجيات ومعايير PEP 8 القياسية لكتابة شيفرات بايثون النظيفة، يُعتبر استخدام المقارنة الصريحة مع القيم البوليانية (مثل == True أو == False) ممارسة برمجية رديئة وغير أصيلة (Unpythonic). التوجيه القياسي يوصي بالاعتماد على التقييم المنطقي الطبيعي للشروط أو استخدام عوامل النفي المتخصصة بدلاً من المقارنات الحرفية غير الفعالة.

4. استخدام عامل النفي المنطقي المتمم (التيلدا ~)

4.1 مفهوم المعامل التكميلي النقطي (Bitwise NOT Operator ~)

يمثل عامل التيلدا (~) في لغة بايثون معامل النفي البتي (Bitwise NOT Operator). من الناحية الرياضية ونظرية المجموعات، يقوم هذا المعامل بحساب المتمم الثنائي (Binary Complement) للمدخلات. عند تطبيقه على المصفوفات والسلاسل البوليانية في بانداس وNumPy، يعمل المعامل ~ على عكس كل قيمة منطقية داخل السلسلة بشكل متجه وعالي الكفاءة؛ فيحول كل True إلى False وكل False إلى True في دورة معالجة واحدة على مستوى البايت.

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

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

4.2 الصيغة التركيبية: df[~df[‘col’].str.contains(‘pattern’)]

تُكتب الصيغة التركيبية لاستخدام عامل النفي التكميلي في بانداس على النحو التالي:

df[~df['column_name'].str.contains('pattern', na=False)]

يتطلب تفكيك هذا التركيب اللغوي فهم أسبقية المعاملات المنطقية في لغة بايثون. عند تنفيذ هذه العبارة، تقوم الدالة str.contains('pattern', na=False) أولاً بمسح العمود النصي وتوليد سلسلة بوليانية تحتوي على True لكل سجل يحتوي على النمط المستهدف. بعد ذلك مباشرة، يتدخل معامل التيلدا ~ الموضوع في مقدمة السلسلة ليقلب هذه القيم المنطقية بشكل كامل، فتصبح السجلات الخالية من النمط هي التي تحمل القيمة True، وبذلك يتم تمرير هذا القناع المتمم إلى إطار البيانات لاستخراج النتائج المطلوبة بدقة تامة.

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

df[~(df['col1'].str.contains('A') & (df['col2'] > 50))]

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

4.3 المقارنة المباشرة بين أسلوب التيلدا وأسلوب المساواة الخاطئة

عند إجراء مقارنة تقنية معمقة بين أسلوب التيلدا (~) وأسلوب المقارنة الصريحة (== False)، تظهر فروق جوهرية تتعلق بالأداء، وقابلية القراءة، وسهولة صيانة الشيفرات البرمجية. في معالجة مجموعات البيانات التي تضم ملايين السجلات، يتفوق أسلوب التيلدا في سرعة التنفيذ وتقليل استهلاك الذاكرة، نظراً لتجنبه إنشاء كائنات وسيطة للمقارنة المنطقية، حيث تنفذ التيلدا عملية قلب البتات في مكانها في الذاكرة (In-place bit-flipping).

من حيث الصيانة والتطوير البرمجي في المشاريع الصناعية والأكاديمية الكبيرة، يوفر أسلوب التيلدا اتساقاً مع بقية دوال بانداس المتقدمة؛ حيث تتماشى التيلدا بسلاسة مع دوال التحديد المكاني .loc[] والتصفية متعددة الأبعاد، وتمنع حدوث الالتباس بين مقارنة القيم ومطابقة الشروط المنطقية.

معيار المقارنة أسلوب التيلدا (~df[‘col’].str.contains) أسلوب المساواة الصريحة (df[‘col’].str.contains == False)
الكفاءة الحسابية عالية جداً (تنفيذ مباشر على مستوى البت في C/NumPy) متوسطة إلى منخفضة (استدعاء إضافي لمعامل المساواة)
الامتثال لمعايير بايثون (PEP 8) متوافق تماماً (Pythonic Standard) غير مستحسن (Anti-pattern)
التعامل مع القيم المفقودة (NaN) دقيق وقابل للضبط المباشر عبر معامل na قد يخفي أخطاء منطقية ويستبعد القيم غير المكتملة دون قصد
التكامل مع الشروط المركبة مرن وسلس عند استخدام الأقواس المناسبة معقد ويتطلب أقواساً مضاعفة لتفادي أخطاء الأسبقية
الوضوح الدلالي للمطورين المحترفين واضح، قياسي، ومتعارف عليه في علم البيانات قد يوحي بقلة الخبرة البرمجية بمكتبة بانداس

5. التصفية المتقدمة لاستبعاد سلاسل نصية متعددة باستخدام التعبيرات النمطية

5.1 الأساس النظري للتعبيرات النمطية (Regex) في البحث النصي

تعتمد مكتبة بانداس بشكل افتراضي على محرك التعبيرات النمطية (Regular Expressions – Regex) المدمج في بيئة بايثون داخل دالة str.contains(). التعبيرات النمطية هي لغة صياغة قوية ومعيارية تُستخدم لوصف أنماط البحث النصي ومطابقتها داخل السلاسل النصية المعقدة. يوفر هذا التكامل لمحرك بانداس قدرة فائقة على تجاوز البحث الحرفي البسيط نحو استكشاف وتصفية الأنماط الدلالية والتركيبية المتقدمة.

من أهم المعاملات في التعبيرات النمطية المستخدمة في التصفية هو المعامل الشريطي (Pipe Operator |)، والذي يمثل البديل المنطقي “أو” (Logical OR) داخل النمط. عند تمرير نمط يحتوي على هذا المعامل، مثل 'patternA|patternB'، يقوم محرك البحث بفحص النص للتحقق من وجود أي من هذه الأنماط المستقلة. إذا تطابق أي نمط منها مع النص، يُعتبر الشرط متحققاً وتُرجع الدالة القيمة True.

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

5.2 استبعاد قائمة من الكلمات المفتاحية في عملية واحدة

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

df[~df['column_name'].str.contains('term1|term2|term3', na=False)]

لتحقيق أقصى قدر من المرونة البرمجية وتجنب كتابة الأنماط النصية يدوياً داخل الكود، يُنصح ببناء نمط البحث ديناميكياً من قائمة بايثون (Python List). يتم ذلك باستخدام التابع القياسي '|'.join()، كما في المثال التالي:

stop_words = ['مسودة', 'ملغي', 'مؤقت', 'اختبار']
pattern = '|'.join(stop_words)
cleaned_df = df[~df['status'].str.contains(pattern, na=False)]

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

5.3 التحكم في معامل التعطيل النمطي regex=False

على الرغم من القوة الفائقة التي تتيحها التعبيرات النمطية، إلا أن هناك حالات تطبيقية تستوجب تعطيلها صراحة وضبط المعامل regex=False داخل دالة str.contains(). يُحول هذا الضبط عملية البحث من مطابقة الأنماط النمطية إلى البحث النصي الحرفي المباشر (Literal Substring Matching)، حيث تبحث الدالة عن السلسلة النصية المدخلة كما هي بالضبط دون أي تفسير دلالي للرموز.

تنشأ الحاجة الحتمية لتعطيل Regex عند البحث عن نصوص تحتوي بطبيعتها على رموز محجوزة في لغة التعبيرات النمطية، مثل علامات الدولار ($)، والأقواس (() أو [])، والنقاط (.)، وعلامات الجمع والضرب (+ و *)، وعلامة الاستفهام (?). إذا تم ترك regex=True (وهو الوضع الافتراضي) أثناء البحث عن نص مثل 'Price ($100)'، سيقوم محرك التعبيرات النمطية بتفسير الأقواس كمجموعات التقاط (Capture Groups) وعلامة الدولار كنهاية للسطر، مما يتسبب في فشل المطابقة أو إطلاق استثناء برمجي من نوع re.error: missing ), unterminated subpattern.

علاوة على تجنب الأخطاء النحوية، يحقق تعطيل التعبيرات النمطية عبر regex=False مكاسب هائلة في الأداء الحسابي وسرعة التنفيذ. تتجاوز عمليات البحث الحرفي مرحلة تحليل النمط وبناء الشجرة النحوية للتعبير النمطي (Regex Compilation)، وتعتمد مباشرة على خوارزميات البحث النصي السريع المكتوبة بلغة C (مثل خوارزمية Boyer-Moore-Horspool)، مما يرفع سرعة التصفية بشكل ملحوظ عند التعامل مع سلاسل نصية ضخمة.

6. معالجة القيم المفقودة (NaN / Null) أثناء التصفية السلبية

6.1 تأثير القيم المفقودة على مخرجات دالة str.contains

تُمثل القيم المفقودة (Missing Values)، والمشار إليها في بانداس بـ NaN (Not a Number) أو None، تحدياً منطقياً وإحصائياً معقداً عند إجراء التصفية النصية. بما أن القيمة المفقودة تعبر عن غياب البيانات، فإنها ليست نصاً حقيقياً يمكن تقييم احتوائه على نمط معين من عدمه. تتبع بانداس في هذا السياق منطقاً ثلاثي القيم (Three-Valued Logic – Kleene Logic)، حيث تكون نتيجة تقييم شرط ما إما True، أو False، أو غير محددة (NaN).

عند تنفيذ الدالة str.contains('pattern') على عمود يحتوي على قيم مفقودة دون تحديد معاملات إضافية، ستُرجع الدالة القيمة NaN في كل صف يقابل قيمة مفقودة في العمود الأصلي. هذا السلوك التلقائي يُنشئ سلسلة بوليانية غير متجانسة تحتوي على قيم منطقية ممزوجة بقيم فارغة.

يكمن الخطر الكارثي هنا عند محاولة تمرير هذه السلسلة مباشرة كقناع منطقي إلى إطار البيانات df[...]؛ حيث يرفض محرك بانداس قبول الأقنعة التي تحتوي على قيم NaN ويطلق فوراً الخطأ الشهير:

ValueError: Cannot mask with non-boolean array containing NA / NaN values

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

6.2 التحكم في المعامل na (تحديد na=False أو na=True)

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

عند الرغبة في تطبيق تصفية سلبية (“لا يحتوي على”) مع الإبقاء على الصفوف التي تحتوي على قيم مفقودة ضمن إطار البيانات النهائي (بافتراض أن القيمة المفقودة لا تحتوي على النمط المرفوض، وبالتالي يجب عدم استبعادها)، يجب ضبط المعامل على النحو التالي:

df[~df['col'].str.contains('pattern', na=False)]

في هذا السيناريو، تقوم الدالة أولاً بتحويل كل قيمة مفقودة إلى False (أي أنها لا تحتوي على النمط)، ثم يأتي دور عامل التيلدا ~ ليقلب هذه القيمة إلى True، مما يضمن بقاء الصف المفقود ضمن البيانات المفلترة.

بالمقابل، إذا كانت السياسة المنهجية للدراسة تتطلب الاستبعاد الصارم لأي سجل غير مكتمل إلى جانب استبعاد النمط النصي، يتم ضبط المعامل كالتالي:

df[~df['col'].str.contains('pattern', na=True)]

هنا، تُسند الدالة القيمة True للقيم المفقودة، ويقوم عامل التيلدا ~ بقلبها إلى False، مما يؤدي إلى إسقاط الصفوف المفقودة والصفوف المحتوية على النمط في خطوة واحدة متناسقة ومنضبطة منطقياً.

6.3 استراتيجيات مسبقة لتنقية السلاسل النصية قبل التصفية

بدلاً من الاعتماد فقط على المعامل na أثناء مرحلة الاستعلام، يُفضل في المشاريع الكبيرة تطبيق استراتيجيات تنقية مسبقة (Pre-filtering Data Imputation) كجزء من خط معالجة البيانات الأولي (Data Preprocessing Pipeline). تهدف هذه الاستراتيجيات إلى معالجة القيم المفقودة وتوحيد بنية العمود النصي قبل الشروع في التصفية المنطقية المعقدة.

تتمثل إحدى الطرق الفعالة في استخدام الدالة fillna() لتعويض القيم المفقودة بسلسلة نصية فارغة (Empty String '') أو بقيمة رمزية دلالية (مثل 'Missing' أو 'غير محدد')، كما في الكود التالي:

df['col_cleaned'] = df['col'].fillna('')

يضمن هذا التحويل أن تكون جميع عناصر العمود من النوع النصي الصريح، مما يلغي تماماً احتمالية ظهور أخطاء ValueError أثناء بناء الأقنعة المنطقية.

هناك نهج آخر يتمثل في استخدام التحويل الصريح للأنواع باستخدام التابع .astype(str). ومع ذلك، يجب توخي الحذر الشديد عند تطبيق هذا التابع؛ حيث يقوم بايثون بتحويل قيمة np.nan إلى السلسلة النصية الحرفية 'nan'. إذا كان استعلام التصفية يبحث عن نمط يتصادف وجوده داخل حروف كلمة “nan” (مثل المقطع ‘an’)، فقد يؤدي ذلك إلى نتائج تصفية خاطئة تماماً وسلوك غير متوقع، مما يجعل استخدام fillna('') هو الخيار الأكثر أماناً وموثوقية في معظم التطبيقات الهندسية.

7. التحكم في حساسية حالة الأحرف والتطابق الجزئي

7.1 إدارة حساسية الأحرف عبر المعامل case=False

تعتبر إدارة حساسية حالة الأحرف (Case Sensitivity) من المتطلبات الجوهرية عند معالجة البيانات النصية المكتوبة باللغة الإنجليزية أو اللغات اللاتينية الأخرى التي تفرق بين الحروف الكبيرة (Uppercase) والحروف الصغيرة (Lowercase). بشكل افتراضي، تعمل دالة str.contains() بحساسية كاملة لحالة الأحرف (case=True)، مما يعني أن البحث عن النمط 'error' لن يتطابق مع 'Error' أو 'ERROR'.

لتجاوز هذا القيد وضمان استبعاد كافة التشكيلات الهجائية للنمط المستهدف، توفر بانداس المعامل case=False. عند تفعيل هذا الخيار:

df[~df['log_message'].str.contains('failed', case=False, na=False)]

يقوم المحرك داخلياً بتوحيد حالة الأحرف (Case Folding) أثناء عملية المطابقة، مما يضمن استبعاد السجلات التي تحتوي على “Failed”، أو “FAILED”، أو “fAiLeD” بشكل آلي ودون الحاجة إلى كتابة تعبيرات نمطية معقدة تشمل كافة التباديل الممكنة لحالة الأحرف.

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

7.2 التمييز بين التطابق الجزئي (Substrings) والتطابق التام للكلمات

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

لتوضيح هذه المعضلة: إذا أردنا استبعاد السجلات التي تحتوي على كلمة “cat” (قط)، فإن البحث الجزئي البسيط سيؤدي إلى استبعاد سجلات تحتوي على كلمات بريئة مثل “caterpillar” (يرقة)، أو “category” (فئة)، أو “location” (موقع)، نظراً لاحتوائها جميعاً على التسلسل الحرفي “cat”. يمثل هذا خطأً منهجياً فادحاً في تصنيف البيانات وتحليلها.

لحل هذه المشكلة وضمان اقتصار الاستبعاد على الكلمة التامة المستقلة، يجب استخدام محددات حدود الكلمات في التعبيرات النمطية، والمعروفة بالرمز b (Word Boundary). يُصاغ الكود البرمجي في هذه الحالة باستخدام السلاسل النصية الخام (Raw Strings) لتفادي تفسير الشرطة المائلة كرمز هروب:

df[~df['description'].str.contains(r'bcatb', case=False, na=False)]

يضمن الرمز b أن النمط “cat” يجب أن يكون مسبوقاً ومتبوعاً بحدود غير حرفية (مثل المسافات، أو علامات الترقيم، أو بدايات ونهايات السطور)، مما يحمي الكلمات المتداخلة لغوياً ويحافظ على سلامة العينة البحثية من الاستبعاد العشوائي.

8. مقارنة الأداء والكفاءة الحاسوبية بين تقنيات الاستبعاد المختلفة

8.1 تحليل استهلاك الموارد وسرعة المعالجة (Benchmarking)

تتفاوت التقنيات المختلفة للتصفية النصية السلبية في بانداس من حيث الكفاءة الزمنية (Execution Time) واستهلاك الذاكرة العشوائية (RAM). عند العمل مع مجموعات بيانات ضخمة (تتجاوز 10 ملايين صف)، تصبح الفروق الزمنية الطفيفة بين الدوال ذات أثر بالغ على كفاءة خوادم التحليل ومسارات الحوسبة المستمرة (CI/CD Data Pipelines).

لقياس زمن الاستجابة بدقة، يُستخدم الأمر السحري %timeit في بيئة Jupyter/IPython لمقارنة السيناريوهات الثلاثة الأساسية: المقارنة الصريحة بـ == False، واستخدام عامل التيلدا مع regex=True، واستخدام عامل التيلدا مع تعطيل محرك الأنماط regex=False. أظهرت الاختبارات القياسية على مصفوفة بيانات مكونة من 5 ملايين سجل نصي النتائج التوضيحية التالية:

الأسلوب البرمجي المستخدم متوسط زمن التنفيذ (مللي ثانية) معدل استهلاك الذاكرة الإضافي التقييم الهندسي للأداء
df[~df['text'].str.contains('pattern', regex=False, na=False)] 185 ms الأدنى (معالجة مباشرة في الذاكرة) الأمثل والأسرع
df[~df['text'].str.contains('pattern', regex=True, na=False)] 420 ms متوسط (بناء شجرة التحليل النمطي) جيد للأنماط المعقدة فقط
df[df['text'].str.contains('pattern', regex=False, na=False) == False] 240 ms مرتفع نسبياً (توليد مصفوفة مقارنة وسيطة) غير فعال هندسياً
الحلقات التكرارية التقليدية df[df['text'].apply(lambda x: ...)] 1850 ms الأعلى (عبء استدعاء مفسر بايثون) سيئ جداً وبطيء

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

8.2 البدائل عالية الأداء: استخدام دوال الفهرسة ومحركات البحث السريع

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

أحد هذه البدائل هو استخدام وحدة numpy.char المتخصصة في الحوسبة النصية على مصفوفات C النقية. تتيح دوال مثل np.char.find() إجراء عمليات مسح سريعة للغاية دون المرور عبر واجهات بانداس الوسيطة. إذا أرجعت الدالة القيمة -1، فهذا يعني أن النمط غير موجود، وهو ما يعادل منطق “لا يحتوي على” بأقل تكلفة معالجة ممكنة:

mask = np.char.find(df['col'].values.astype(str), 'pattern') == -1
filtered_df = df[mask]

بالإضافة إلى ذلك، فإن الانتقال إلى المحركات الحديثة مثل Polars أو توظيف نوع البيانات الجديد string[pyarrow] المتاح في إصدارات بانداس الحديثة (Pandas 2.0+) يوفر تحسيناً هائلاً في الأداء. يعتمد محرك Apache Arrow على تخزين النصوص في كتل ذاكرة متلاصقة تدعم الحوسبة المتوازية وتلغي مشكلة تشتت مؤشرات الذاكرة التي تعاني منها سلاسل بايثون التقليدية، مما يجعل التصفية النصية أسرع بعدة أضعاف.

9. الأخطاء الشائعة وحالات الفشل البرمجي وكيفية تصحيحها

9.1 أخطاء القيم غير النصية والأنواع المختلطة (Mixed Types Error)

من أكثر الأخطاء شيوعاً وإحباطاً لمحللي البيانات هو ظهور استثناء AttributeError: Can only use .str accessor with string values أو حدوث أخطاء صامتة ينتج عنها تصفية مشوهة. يحدث هذا الخطأ عندما يحتوي العمود المستهدف على خليط من الأنواع البيانية (Object Dtype)، مثل وجود أرقام صحيحة (integers)، أو قيم عشرية (floats)، أو كائنات برمجية متداخلة جنباً إلى جنب مع النصوص.

للتحقق من تجانس البيانات، يجب فحص توزيع أنواع البيانات داخل العمود باستخدام الشيفرة الاستكشافية التالية:

print(df['column_name'].apply(type).value_counts())

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

df['column_name'] = df['column_name'].astype(str)
# أو استخدام معالجة انتقائية
df['column_name'] = df['column_name'].fillna('').apply(lambda x: str(x) if not isinstance(x, str) else x)

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

9.2 أخطاء أسبقية المعاملات والأقواس المفقودة

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

على سبيل المثال، عند كتابة الشيفرة التالية بشكل خاطئ:

# كود خاطئ يسبب انهياراً أو سلوكاً غير متوقع
df[~df['col1'].str.contains('A') & df['col2'] == 10]

يقوم مفسر بايثون بتفسير المعامل & بأسبقية أعلى من معامل المقارنة ==، فيحاول إجراء عملية “AND” بتية بين السلسلة النصية ورقم صحيح، مما يؤدي إلى ظهور الخطأ:

TypeError: Cannot perform 'rand_' with a dtyped [object] array and scalar of type [int]

لتصحيح هذا الخطأ وضمان التنفيذ المنطقي السليم، يجب الالتزام بالقالب القياسي التالي، الذي يحيط كل شرط مستقل بأقواس محكمة:

# القالب القياسي الخالي من الأخطاء
mask = (~df['col1'].str.contains('A', na=False)) & (df['col2'] == 10)
filtered_df = df[mask]

9.3 أخطاء التعامل مع الرموز الخاصة والتعبيرات النمطية غير الصالحة

عندما تتضمن السلاسل النصية المراد استبعادها رموزاً خاصة محجوزة لمحرك التعبيرات النمطية (مثل: [, ], (, ), {, }, *, +, ?, ^, $, |, )، فإن تمريرها مباشرة إلى دالة contains دون احتراز يؤدي إلى انهيار البرنامج بإطلاق استثناء re.error بسبب عدم اكتمال النمط أو وجود بناء نحوي غير صالح.

لتوضيح ذلك، لنفترض أننا نريد استبعاد السجلات التي تحتوي على الوسم النصي '[PROMO]'. إذا كُتب الكود بالشكل التالي:

df[~df['text'].str.contains('[PROMO]')] # خطأ دلالي

لن يتعامل محرك التعبيرات النمطية مع الأقواس المربعة كنصوص، بل سيفسرها كفئة أحرف (Character Class)، مما يعني البحث عن أي سجل يحتوي على الحرف ‘P’ أو ‘R’ أو ‘O’ أو ‘M’، وبالتالي استبعاد كل نص يحتوي على أي حرف من هذه الحروف، وهو ما يدمر البيانات بالكامل!

لعلاج هذه المشكلة، توجد طريقتان قياسيتان:

  • الطريقة الأولى (التعطيل الحرفي): إذا كان البحث لا يتطلب أنماطاً مركبة، يتم ببساطة ضبط regex=False.
  • الطريقة الثانية (الهروب المنظم): إذا كان التعبير يجمع بين الرموز الخاصة وأنماط نمطية أخرى، يتم استخدام دالة الهروب المعيارية re.escape() لتأمين السلسلة تلقائياً:

import re
safe_pattern = re.escape('[PROMO]')
filtered_df = df[~df['text'].str.contains(safe_pattern, na=False)]

10. تطبيقات منهجية في تنقية وتحليل البيانات الواقعية

10.1 تنقية البيانات التجريبية واستبعاد الاستجابات غير الجادة

في الأبحاث الأكاديمية والمسوح الميدانية التي تعتمد على استبانات مفتوحة، يواجه الباحثون تحدي تلوث البيانات باستجابات روبوتية مؤتمتة (Bot Submissions) أو إجابات عشوائية يكتبها مشاركون غير جادين لاجتياز الاستبيان بسرعة والحصول على المكافآت المالية. تتضمن هذه الاستجابات عادةً نصوصاً نموذجية مثل: “asdasd”، “no comment”، “test”، “N/A”، أو جمل منسوخة ومكررة.

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

invalid_patterns = ['asdf', 'test', 'لا يوجد تعليق', 'لا اعلم', 'تجربة', 'none']
pattern_regex = '|'.join([re.escape(p) for p in invalid_patterns])
clean_survey_df = df[~df['open_ended_response'].str.contains(pattern_regex, case=False, na=False)]

يساهم هذا الإجراء في خفض معدل الضوضاء في العينة، ويوثق في منهجية البحث كخطوة لضبط جودة البيانات (Quality Assurance Protocol)، مما يعزز الصدق البنائي (Construct Validity) للنتائج ويدعم موثوقية الاستنتاجات العلمية المنشورة.

10.2 استبعاد مصطلحات التشويش في تحليل المشاعر والبيانات النفسية

في مشاريع تحليل المشاعر (Sentiment Analysis) وتعدين النصوص النفسية والاجتماعية المستخرجة من شبكات التواصل الاجتماعي، تتأثر النماذج التنبؤية سلباً بوجود منشورات ترويجية، أو وسوم تسويقية مضللة، أو اقتباسات إخبارية محايدة لا تعكس المشاعر الحقيقية للمستخدمين.

من خلال التصفية السلبية المتقدمة، يمكن لمحلل البيانات استبعاد النصوص التي تحتوي على وسوم دعائية (مثل #ad, #sponsor, #تخفيضات, #خصم) قبل البدء في حساب درجات القطبية العاطفية (Polarity Scores):

spam_tags = [r'#adb', r'#promob', r'#sponsorb', r'#خصمb', r'#تسوقb']
spam_filter = '|'.join(spam_tags)
sentiment_df = raw_tweets[~raw_tweets['tweet_text'].str.contains(spam_filter, case=False, na=False)]

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

10.3 بناء سيناريو متكامل لمعالجة مجموعة بيانات متعددة المتغيرات

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

يتطلب التحليل تنقية البيانات عبر مسار معالجة متعدد الشروط يستبعد:

  1. السجلات التي تحتوي على كلمات الاختبار الداخلي (مثل: “System Test”, “Sandbox”).
  2. الشكاوى الناتجة عن محاولات احتيال معروفة تم وسمها بعبارة “Fraud Alert”.
  3. السجلات التي تحتوي على قيم مفقودة في عمود الشكوى مع الاحتفاظ بالتقييمات الرقمية الصالحة.

يتم تنفيذ هذا السيناريو المتكامل برمجياً عبر الشيفرة المتسلسلة التالية:

# 1. تنظيف أولي للأعمدة النصية
df['complaint_text'] = df['complaint_text'].fillna('NO_TEXT')

# 2. بناء الأنماط المستبعدة
exclusion_patterns = r'System Test|Sandbox|Fraud Alert|Test Account'

# 3. صياغة القناع المنطقي المركب
valid_mask = (
    (~df['complaint_text'].str.contains(exclusion_patterns, case=False, regex=True)) &
    (df['complaint_text'] != 'NO_TEXT') &
    (df['customer_rating'].notna())
)

# 4. استخراج المصفوفة النهائية وإعادة تعيين الفهرس
final_clean_df = df.loc[valid_mask].reset_index(drop=True)

ينتج عن هذا الخط المتكامل مصفوفة نظيفة تماماً، جاهزة ومؤهلة لتغذية خوارزميات التعلم الآلي أو استخراج تقارير الأداء التنفيذي بمصداقية مطلقة.

11. الدمج مع دوال الاستعلام المتقدمة في بانداس

11.1 تطبيق التصفية السلبية باستخدام دالة df.query()

توفر مكتبة بانداس دالة الاستعلام المتقدمة df.query()، والتي تتيح كتابة شروط التصفية في صورة تعبيرات نصية سلسة ومقروءة تعتمد على صياغة لغوية قريبة من لغة الاستعلامات البنيوية (SQL). تكتسب دالة query شهرة واسعة لقدرتها على تعزيز قابلية قراءة الأكواد المعقدة وتسهيل فهم المسارات التحليلية للمطورين والباحثين.

يمكن تطبيق التصفية السلبية النصية داخل بيئة query باستخدام معامل النفي ~ واستدعاء الواجهة النصية مباشرة داخل التعبير النصي:

cleaned_df = df.query('~column_name.str.contains("pattern", na=False)', engine='python')

يجب ملاحظة أنه عند استدعاء التوابع النصية المعقدة داخل query()، يلزم في كثير من الأحيان تحديد المحرك كـ engine='python' بدلاً من المحرك الافتراضي numexpr؛ لأن الأخير مُحسن للعمليات الحسابية والعددية السريعة ولا يدعم كافة توابع الفهرسة النصية الموسعة لـ .str.

تكمن الميزة الكبرى لدالة query في قدرتها على دمج المتغيرات الخارجية الديناميكية بسلاسة باستخدام رمز @، مثل:

excluded_word = "spam"
result = df.query('~text_column.str.contains(@excluded_word, na=False)', engine='python')

11.2 التكامل مع دالة loc والفهرسة الشرطية المتقدمة

تُمثل الدالة df.loc[] المعيار الأكثر قوة وموثوقية في مكتبة بانداس للوصول إلى البيانات وتعديلها بناءً على التسميات والفهارس المنطقية. يسمح التكامل بين الأقنعة المنطقية السلبية ودالة loc بإجراء تصفية مزدوجة تستهدف الصفوف والأعمدة في خطوة برمجية واحدة، كما في الصيغة التالية:

subset = df.loc[~df['notes'].str.contains('ignore', na=False), ['user_id', 'transaction_amount', 'date']]

أهم ميزة لاستخدام df.loc تظهر عند الرغبة في تعديل أو تحديث قيم معينة في الصفوف المستوفية للشرط السلبي فقط، دون الرغبة في حذف بقية الصفوف. على سبيل المثال، إذا أردنا تعيين قيمة علم تصنيفي (Flag) جديد للعملاء الذين لا تحتوي سجلاتهم على كلمة “مخالفة”:

mask = ~df['history'].str.contains('مخالفة', na=False)
df.loc[mask, 'status_tier'] = 'Eligible'

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

11.3 استخدام دوال lambda و apply كبدائل مرنة للشروط المعقدة

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

في مثل هذه السيناريوهات الاستثنائية، تبرز الدالة apply() مع الدوال المجهولة (Lambda Functions) كأداة مرنة للغاية لبناء مرشحات سلبية مخصصة:

# دالة تحقق مخصصة
def is_valid_text(text):
    if not isinstance(text, str): return True
    # منطق معقد: استبعاد النصوص التي تحتوي على أكثر من 3 أرقام أو كلمات محظورة محددة
    if sum(c.isdigit() for c in text) > 3: return False
    return True

filtered_df = df[df['text'].apply(is_valid_text)]

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

12. أفضل الممارسات الهندسية والمنهجية لتوثيق ومعالجة البيانات النصية المستبعدة

12.1 التوثيق الأكاديمي لقرارات استبعاد البيانات وتأثيرها المنهجي

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

من المتطلبات الإحصائية الأساسية حساب وتوثيق “معدل فقدان العينة” (Sample Attrition Rate) الناتج عن عمليات التصفية النصية. يتم حساب هذه النسبة من خلال المعادلة:

معدل الفقدان (%) = ((حجم العينة الأولي - حجم العينة بعد التصفية) / حجم العينة الأولي) × 100

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

علاوة على ذلك، تفرض المعايير الهندسية الصارمة عدم الكتابة فوق البيانات الخام الأصلية (Raw Data Invariance). يجب دائماً الاحتفاظ بملف البيانات الأصلي في حالة قراءة فقط (Read-only)، وإجراء كافة عمليات التصفية والتحويلات داخل مسارات برمجية تنتج مصفوفات مشتقة جديدة، مما يتيح مراجعة خطوات التحول والتراجع عنها عند الحاجة دون فقدان البيانات المصدرية.

12.2 هندسة الكود النظيف وقابلية إعادة الاستخدام في بايثون

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

يوفر استخدام تلميحات الأنواع (Type Hinting) والتوثيق المضمن (Docstrings) وضوحاً فائقاً لطبيعة المدخلات والمخرجات المتوقعة، كما يوضح القالب القياسي التالي:

from typing import List, Optional
import pandas as pd

def filter_out_patterns(
    data: pd.DataFrame,
    target_column: str,
    patterns: List[str],
    case_sensitive: bool = False,
    keep_na: bool = True
) -> pd.DataFrame:
    """
    تصفية إطار البيانات باستبعاد الصفوف التي تحتوي على أي من الأنماط المحددة.
    """
    if target_column not in data.columns:
        raise KeyError(f"العمود '{target_column}' غير موجود في إطار البيانات.")
    
    combined_regex = '|'.join(patterns)
    mask = ~data[target_column].astype(str).str.contains(
        combined_regex,
        case=case_sensitive,
        na=not keep_na
    )
    return data.loc[mask].reset_index(drop=True)

بالإضافة إلى كتابة الدوال النمطية، يُعد بناء اختبارات الوحدة (Unit Tests) باستخدام إطار مثل pytest ممارسة أساسية للتحقق من أن دوال التصفية تتصرف كما هو متوقع مع الحالات الحدية (Edge Cases)، مثل السلاسل الفارغة، والأعمدة التي تحتوي على قيم NaN فقط، والنصوص التي تتضمن رموزاً خاصة.

12.3 بناء سلاسل معالجة البيانات النصية (Method Chaining) بأمان

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

يمكن دمج التصفية السلبية بسلاسة داخل سلسلة المعالجة باستخدام الدالة pipe() أو loc[]، بالتكامل مع دوال التجميع والترتيب وحذف القيم الفارغة:

final_report = (
    raw_df
    .dropna(subset=['user_id', 'feedback'])
    .loc[lambda d: ~d['feedback'].str.contains('spam|bot|advertisement', case=False, na=False)]
    .assign(feedback_length=lambda d: d['feedback'].str.len())
    .groupby('user_tier')
    .agg(avg_rating=('rating', 'mean'), count=('user_id', 'count'))
    .sort_values(by='avg_rating', ascending=False)
)

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

خاتمة

استعرضنا في هذا الدليل المرجعي الشامل كافة الأبعاد النظرية والهندسية لعملية التصفية النصية السلبية “لا يحتوي على” في مكتبة بانداس. اتضح لنا بجلاء أن أسلوب استخدام عامل النفي التكميلي البتي (التيلدا ~) بالتكامل مع الدالة str.contains() يمثل الخيار الهندسي الأمثل من حيث الأداء، وقابلية القراءة، والامتثال لمعايير بايثون القياسية، متفوقاً بشكل حاسم على أساليب المقارنة الصريحة بـ == False.

كما بيّنا الأهمية الفائقة للإدارة الدقيقة للمعاملات المدمجة، مثل na=False لحماية البيانات من الانهيار عند وجود قيم مفقودة، وregex=False لتحقيق قفزات نوعية في سرعة المعالجة عند البحث الحرفي وتجنب أخطاء الرموز الخاصة، وcase=False لتوحيد المطابقة اللغوية. إن الإلمام بهذه التفاصيل الدقيقة يمكّن مهندسي البيانات والباحثين من بناء خطوط معالجة متقدمة وموثوقة قادرة على التعامل مع أضخم مجموعات البيانات بكفاءة واحترافية.

المراجع

★

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

5.0 / 5 • 7 تقييمات

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

looti, M. (2026, سبتمبر 4). بانداس: كيفية التصفية حسب “لا يحتوي على. عرب سايكلوجي. https://arabpsychology.com/statistics/pandas-how-to-filter-for-not-contains/
looti, Mohammed. “بانداس: كيفية التصفية حسب “لا يحتوي على.” عرب سايكلوجي, 4 سبتمبر 2026, https://arabpsychology.com/statistics/pandas-how-to-filter-for-not-contains/.
looti, Mohammed. “بانداس: كيفية التصفية حسب “لا يحتوي على.” عرب سايكلوجي. سبتمبر 4, 2026. https://arabpsychology.com/statistics/pandas-how-to-filter-for-not-contains/.