برمجة بايثون, تحليل البيانات الإحصائي, علم البيانات

كيفية إنشاء متغيرات فئوية في بانداس (مع أمثلة)


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

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

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

1. مقدمة شاملة حول المتغيرات الفئوية (Categorical Variables) في مكتبة بانداس

1.1 مفهوم المتغيرات الفئوية في علم البيانات والإحصاء

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

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

وتشيع تطبيقات المتغيرات الفئوية في مجالات متعددة، لا سيما في الدراسات السلوكية والنفسية وعلم النفس القياسي (Psychometrics)، حيث يتم قياس السمات والاتجاهات عبر مقاييس ليكرت (Likert Scales) التي تتراوح بين “أوافق بشدة” و”لا أوافق بشدة”. كما تمتد إلى قطاعات الاقتصاد والطب السريري لتصنيف مراحل المرض ومجموعات العلاج والدواء الوهمي (Placebo). وهنا يأتي دور مكتبة Pandas لتوفير بنيات برمجية مخصصة تجعل التعامل مع هذه التعقيدات النوعية أمراً بالغ السلاسة والاحترافية.

1.2 لماذا نستخدم نوع البيانات Categorical في Pandas بدلاً من الأنواع التقليدية؟

يقدم التحول إلى استخدام نوع البيانات category بدلاً من النوع النصي العام object فوائد هندسية وحسابية حاسمة تبرز بوضوح عند معالجة البيانات الضخمة. الميزة الأولى والأكثر تأثيراً هي الخفض الهائل في استهلاك الذاكرة العشوائية (RAM)؛ فبدلاً من تخزين النصوص المتكررة في كل صف كمؤشرات مستقلة لكائنات نصية في لغة بايثون، يقوم Pandas بتخزين النصوص الفريدة مرة واحدة فقط في جدول داخلي، بينما تُخزن البيانات الفعلية في الأعمدة على هيئة مصفوفة من الأعداد الصحيحة الصغيرة (Integers) التي تشير إلى تلك الفئات، مما يوفر في كثير من الأحيان ما يزيد عن 80% إلى 95% من حجم الذاكرة المستهلكة.

الميزة الثانية تتمثل في تحسين الأداء الحسابي وسرعة تنفيذ العمليات المعقدة؛ إذ إن عمليات التجميع (Grouping) والترشيح (Filtering) والفرز (Sorting) تصبح أسرع بكثير لأنها تنفذ على أعداد صحيحة بدلاً من إجراء مقارنات نصية مجهدة برمجياً على مستوى المحارف (Characters). ويتيح ذلك لمكتبة Pandas استغلال سرعة لغة C المدمجة ومكتبة NumPy لتنفيذ العمليات بسرعة فائقة.

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

1.3 نظرة عامة على الطرق الرئيسية لإنشاء المتغيرات الفئوية

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

المسار الأول هو الإنشاء اليدوي المباشر من الصفر (From Scratch)، حيث يتم استخدام الفئة المباشرة pd.Categorical() لتعريف متغير فئوي عبر تمرير قوائم أو مصفوفات أولية وتحديد الفئات المسموحة صراحة، وهو أسلوب مثالي في بيئات التجارب وبناء المتغيرات الوصفية الأولية. أما المسار الثاني فيعتمد على التقطيع الإحصائي للمتغيرات الرقمية المستمرة (Binning) عبر استخدام الدوال المتخصصة مثل pd.cut() لتقسيم البيانات إلى فترات متساوية العرض، و pd.qcut() لتقسيم البيانات بناءً على التوزيع التكراري والربيعيات المئينية.

المسار الثالث يتجسد في التحويل الصريح للأنواع القائمة مسبقاً (Type Casting) باستخدام الدالة واسعة الانتشار astype('category')، والتي تُعد الخيار الأكثر شيوعاً لتحويل الأعمدة النصية أو الرقمية الموجودة مسبقاً في إطار البيانات DataFrame. وأخيراً، يبرز المسار المتقدم المعتمد على استدعاء الكائن الهيكلي CategoricalDtype من وحدة pandas.api.types، والذي يتيح التحكم الكامل والصارم في تحديد قائمة الفئات المعتمدة، وترتيبها الهرمي، وفرضها كقالب موحد عبر إطارات بيانات متعددة.

2. الفرق الجوهري بين نوع البيانات الفئوي (category) ونوع الكائن السلسلي (object)

2.1 التمثيل الداخلي للبيانات في الذاكرة: مقارنة تقنية

لفهم الفارق التقني العميق بين النوعين، يجب استكشاف الآلية التي تدير بها لغة Python ومكتبة Pandas الذاكرة المنخفضة المستوى. عندما يتم تخزين عمود نصي كنوع object، فإن مصفوفة NumPy التحتية لا تخزن النصوص ذاتها داخل كتل ذاكرية متجاورة، بل تخزن مصفوفة من المؤشرات (Pointers) التي يشير كل منها إلى كائن نصي حر مبعثر في كومة الذاكرة (Python Heap Memory). يتسبب ذلك في حمل ذاكري مضاعف (Overhead) لكل قيمة نصية، بالإضافة إلى فقدان ميزة النفاذ المتسلسل السريع للذاكرة وتشتت الكاش (Cache Misses).

في المقابل، يعتمد نوع البيانات category بنية معمارية مزدوجة مستوحاة من جداول البحث (Lookup Tables). تتكون هذه البنية من مكونين رئيسيين: الأول هو مصفوفة الفئات categories، وهي عبارة عن فهرس (Index) يحتوي على القيم الفريدة فقط دون أي تكرار؛ والثاني هو مصفوفة الأكواد codes، وهي مصفوفة NumPy مدمجة من الأعداد الصحيحة الصغيرة (مثل int8 أو int16 بحسب عدد الفئات الفريدة). إذا احتوى العمود على مليون سجل لثلاث دول فقط، فإن الذاكرة تخزن ثلاثة نصوص في الفهرس، ومليون عدد صحيح من فئة البايت الواحد (8-bit) في مصفوفة الأكواد، مما يقلل البصمة الذاكرية بصورة جذرية.

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

2.2 فحص الأنواع باستخدام خصائص dtypes و info()

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

ومع ذلك، فإن الفحص السطحي عبر دالة df.info() الاعتيادية قد يعطي قراءات مضللة لاستهلاك الذاكرة، لأنها تحسب فقط حجم المؤشرات وليس حجم كائنات النصوص الفعلية في الذاكرة. ولإجراء تحليل دقيق وعميق، يجب استدعاء الدالة المتقدمة df.info(memory_usage='deep')، حيث تجبر هذه المعاملة مكتبة Pandas على مسح كافة كائنات الذاكرة في لغة بايثون وتقديم الحجم الحقيقي المستهلك بالبايت والميجابايت.

وعند تطبيق دالة df.describe() الإحصائية، يُلاحظ تمايز سلوكي لافت بين النوعين؛ فالأعمدة ذات النوع category توفر ملخصاً إحصائياً وصفياً نوعياً يتضمن إجمالي عدد القيم غير المفقودة (count)، وعدد الفئات الفريدة (unique)، والقيمة الأكثر تكراراً (top)، والتردد الخاص بالقيمة الأعلى (freq)، مع إمكانية إظهار خصائص الترتيب الأدنى والأقصى إذا كان المتغير الفئوي معرفاً كمتغير ترتيبي مرتب، وهو ما يثري التحليل الأولي بصورة آلية.

2.3 حالات الاستخدام المثالية لكل نوع بياني

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

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

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

3. الطريقة الأولى: إنشاء متغير فئوي من الصفر (From Scratch)

3.1 الإنشاء المباشر عبر قواميس البيانات وبناء إطار البيانات DataFrame

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

إذا قمنا بتعريف قاموس يحتوي على مفتاح 'team' بقيم نصية مثل ['A', 'B', 'A', 'C', 'B', 'A'] ومفتاح 'points' بقيم عددية مثل [10, 15, 12, 19, 14, 11]، وتمريره للدالة pd.DataFrame()، فإن العمود الرياضي سيكتسب تلقائياً النوع object. على الرغم من أن هذا السلوك الافتراضي يضمن سهولة البناء الأولي، إلا أنه يفتقر إلى القيود المنطقية التي تميز الفئات الصريحة.

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

3.2 استخدام الفئة pd.Categorical لإنشاء متغيرات صريحة

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

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

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

3.3 إدراج المتغيرات الفئوية في سلاسل Pandas Series وإطارات البيانات

بمجرد إنشاء الكائن الفئوي باستخدام pd.Categorical، يمكن دمجه بسلاسة متناهية في سلاسل pd.Series أو تعيينه كعمود جديد داخل إطار بيانات قائم بالفعل. يتم ذلك ببساطة عبر إسناد الكائن الناتج مباشرة إلى اسم العمود المستهدف، مثل إسناد متغير فئات الأداء الوظيفي إلى عمود df['performance_level'].

وعند الرغبة في دمج سلاسل فئوية متعددة أو ربط إطارات بيانات باستخدام دوال الدمج مثل pd.concat() أو pd.merge()، تحافظ مكتبة Pandas على السمات الفئوية بشرط تطابق الفئات المعرفة وترتيبها في كافة الأطراف المدمجة. وإذا حدث اختلاف طفيف في الفئات بين السلاسل، فإن Pandas قد يلجأ تلقائياً إلى تحويل العمود الناتج إلى نوع object كإجراء احترازي لتجنب فقدان البيانات، ما لم يتم توحيد نوع البيانات الفئوي مسبقاً.

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

4. الطريقة الثانية: تحويل المتغيرات الرقمية إلى متغيرات فئوية باستخدام pd.cut()

4.1 مفهوم التقطيع المتساوي والتقطيع المخصص (Binning)

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

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

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

4.2 شرح معاملات الدالة pd.cut بالتفصيل التطبيقي

تُعد الدالة pd.cut() الأداة الأساسية في مكتبة Pandas المخصصة لتنفيذ عمليات التقطيع المستمر بناءً على قيم الحدود والفواصل العددية. تتميز هذه الدالة بحزمة من المعاملات الدقيقة التي تمنح المحلل مرونة حسابية فائقة للتحكم في كيفية بناء الفترات الرياضية وتسميتها:

  • معامل bins: يقبل هذا المعامل إما عدداً صحيحاً يحدد عدد الفترات المتساوية في العرض التي سيقوم النظام بحسابها آلياً بين أدنى وأعلى قيمة، أو قائمة من الأعداد الحقيقية التي تحدد نقاط الفصل الدقيقة (Edges) لكل فترة (مثل: [0, 50, 70, 85, 100]).
  • معامل labels: يتيح تمرير قائمة من الأسماء النصية لتسمية الفترات الناتجة (مثل: ['ضعيف', 'متوسط', 'جيد', 'ممتاز']). إذا تُرِك هذا المعامل بقيمته الافتراضية None، فإن Pandas سيعيد نصوص الفترات الرياضية نفسها (مثل: (0, 50]).
  • معامل right: معامل منطقي يأخذ القيمة True افتراضياً، مما يعني أن الفترات تكون نصف مفتوحة ومغلقة من اليمين (a, b]؛ أي أن الفترة تتضمن الحد الأعلى وتستثني الحد الأدنى. وإذا عُيّن إلى False، تصبح الفترات مغلقة من اليسار [a, b).
  • معامل include_lowest: يأخذ القيمة False افتراضياً، وفي حال تعيينه إلى True مع كون right=True، فإنه يقوم بفتح استثناء دقيق ليجعل الفترة الأولى مغلقة بالكامل من الطرفين ليشمل الحد الأدنى الفعلي لأصغر قيمة في البيانات، متفادياً تحويل أصغر رقم إلى قيمة مفقودة.

4.3 أمثلة عملية تفصيلية على دالة pd.cut()

لتوضيح التطبيق العملي، لنفترض وجود إطار بيانات يضم رواتب عينة مكونة من آلاف الموظفين تتراوح رواتبهم بين 3000 و 30000 دولار شهرياً. لتقسيم هذه الرواتب إلى شرائح دخل اقتصادية معتمدة، يمكن تحديد مصفوفة الحدود: bins = [0, 5000, 12000, 20000, float('inf')] مع تحديد مصفوفة التسميات التفسيرية: labels = ['منخفض', 'متوسط', 'مرتفع', 'مرتفع جداً'].

عند تطبيق الأمر pd.cut(df['salary'], bins=bins, labels=labels, include_lowest=True) وإسناد الناتج لعمود جديد باسم df['income_bracket']، ينشئ Pandas متغيراً فئوياً عالي الكفاءة ينسب كل موظف فورياً إلى شريحته الدقيقة. والجدير بالذكر أن الناتج يكتسب تلقائياً صفة المتغير الفئوي المرتب (Ordered Categorical)، حيث يدرك النظام أن “مرتفع جداً” أعلى تراتبياً من “مرتفع” وهكذا.

يمكن بعد ذلك تطبيق الدالة df['income_bracket'].value_counts(sort=False) لتحليل التوزيع التكراري الدقيق للموظفين عبر الشرائح المختلفة، مما يوفر رؤية إحصائية فورية حول التركيبة الاقتصادية للعينة دون الحاجة لكتابة حلقات تكرارية معقدة بلغة بايثون.

5. تقسيم البيانات بناءً على التوزيع الإحصائي والربيعيات باستخدام pd.qcut()

5.1 الفرق الإحصائي بين pd.cut و pd.qcut

يكمن الاختلاف الجوهري بين الدالتين pd.cut() و pd.qcut() في الأساس الرياضي المعتمد لتقسيم البيانات. تعتمد الدالة pd.cut() على التقطيع المتساوي لعرض الفترات (Equal-width Binning)؛ أي أنها تقسم المدى العددي الكلي إلى مسافات متساوية بغض النظر عن كثافة توزيع البيانات داخل كل فترة، مما قد يؤدي في التوزيعات الملتوية بشدة (Skewed Distributions) إلى تجمع 90% من العينات في فترة واحدة وبقاء الفترات الأخرى شبه فارغة.

في المقابل، تعتمد الدالة pd.qcut() على التقطيع المتساوي للترددات الإحصائية (Equal-frequency Binning) استناداً إلى الربيعيات والمئينات الإحصائية (Quantiles). تضمن هذه الدالة أن تحتوي كل فئة ناتجة على نفس العدد تقريباً من المشاهدات والسجلات، بصرف النظر عن تباعد القيم العددية أو تقاربها.

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

5.2 تطبيق التقطيع الربيعي والعشيري والمئيني

توفر الدالة pd.qcut() مرونة استثنائية في تحديد عدد ومواقع الشرائح التوزيعية المطلوبة. لتقسيم مجموعة بيانات إلى أرباع إحصائية متساوية (Quartiles)، يكفي تمرير القيمة العددية q=4، حيث يقوم النظام بحساب الربيعيات الثلاثة (Q1, Q2, Q3) ويقسم البيانات إلى أربع مجموعات تحتوي كل منها على 25% من إجمالي السجلات، ويمكن تمرير تسميات دلالية مثل labels=['Q1', 'Q2', 'Q3', 'Q4'].

وبالمثل، يمكن تنفيذ التقطيع العشيري (Deciles) بتمرير q=10 لتقسيم درجات اختبار ذكاء أو كفاءة وظيفية إلى عشر شرائح متساوية تضم كل منها 10% من العينة، وهو إجراء شائع جداً في المعايير النفسية والتربوية لتحديد الرتب المئينية للأفراد ومقارنتهم بالمجتمع المعياري.

علاوة على ذلك، تتيح الدالة تمرير مصفوفة مخصصة من النسب الاحتمالية المئوية بدلاً من عدد صحيح، مثل تمرير q=[0, 0.1, 0.5, 0.9, 1.0]. يؤدي هذا التخصيص إلى عزل الشريحة الدنيا (أدنى 10%) والشريحة العليا (أعلى 10%) مع تقسيم النصف الأوسط إلى كتلتين متساويتين، مما يتيح دراسة وتحليل الفئات المتطرفة سلوكياً أو اقتصادياً بدقة إحصائية متناهية.

5.3 معالجة التكرارات والبيانات المزدحمة بواسطة معامل duplicates

تظهر مشكلة إحصائية وحسابية شائعة عند تطبيق التقطيع المئيني pd.qcut() عندما تحتوي مجموعة البيانات على عدد كبير جداً من القيم المكررة المتطابقة، لا سيما القيمة صفر في البيانات المتناثرة (Sparse Data). في هذه الحالة، قد تتساوى قيمة الربيع الأول مع قيمة الربيع الثاني أو الحد الأدنى، مما يؤدي إلى تكرار حدود الفترات (Bin Edges) وتوليد خطأ برمجي شهير من نوع ValueError: Bin edges must be unique.

لحل هذه المعضلة الحسابية بأناقة وموثوقية، توفر الدالة المعامل duplicates='drop'. عند تفعيل هذا المعامل، يقوم Pandas بفحص الحدود المئينية المحسوبة، وفي حال اكتشاف أي تكرار بين الحدود، فإنه يقوم بإسقاط الحد المكرر آلياً ودمج الفترات المتداخلة في فترة واحدة متماسكة دون إيقاف تنفيذ الكود.

يجب على المحلل الانتباه إلى أنه عند إسقاط الحدود المكررة، قد يقل عدد الفئات الإجمالي الناتج عن العدد الأصلي الممرر في المعامل q. لذا، عند تمرير أسماء الفئات عبر معامل labels بالتزامن مع duplicates='drop'، قد يحدث تعارض في الأبعاد إذا لم يتم ضبط التسميات بما يتوافق مع العدد الفعلي للفئات الفريدة الناتجة بعد الدمج.

6. التحويل الصريح لنوع البيانات باستخدام الدالة astype(‘category’)

6.1 تحويل الأعمدة النصية القائمة (String/Object) إلى فئوية

يُعد التحويل الصريح للأنواع (Explicit Type Casting) عبر الدالة astype('category') الأسلوب الأكثر انتشاراً واستخداماً في خطوط المعالجة اليومية لعلماء البيانات. يُطبق هذا التحويل مباشرة على أي سلسلة Series أو عمود داخل DataFrame تم تحميله مسبقاً من ملفات نصية مثل CSV أو قواعد بيانات SQL.

تتم عملية التحويل الفردي لعمود محدد عبر صيغة برمجية مباشرة: df['city'] = df['city'].astype('category'). في هذه اللحظة، يقوم Pandas بمسح العمود، واستخراج قائمة المدن الفريدة، وبناء مصفوفة الأكواد الداخلية، وتحويل نوع العمود فورياً، مما يؤدي إلى انخفاض فوري في الذاكرة المستهلكة وتحسن ملموس في سرعة استجابة العمليات اللاحقة على هذا العمود.

كما تتيح الدالة إمكانية التحويل الجماعي الفائق لعدة أعمدة فئوية في خطوة برمجية موحدة باستخدام القواميس التعيينية. يمكن تمرير قاموس للدالة df = df.astype({'gender': 'category', 'country': 'category', 'status': 'category'})، مما يضمن تحسين كفاءة إطار البيانات بالكامل وتجهيزه للتحليل الإحصائي في سطر برمجي واحد يتسم بالأناقة والقابلية للصيانة.

6.2 تحويل الأعمدة الرقمية المنفصلة (Discrete Numerics) إلى فئات

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

يؤدي تطبيق df['gender'] = df['gender'].astype('category') إلى حماية التحليل من هذه الأخطاء الكارثية؛ حيث يُجرد العمود من خواصه الحسابية الجبرية ويمنع إجراء عمليات الجمع والضرب عليه، مع الاحتفاظ بهوية كل كود كفئة مستقلة بذاتها. وتتعرف نماذج الانحدار المتقدمة على هذا التحول فتقوم تلقائياً بمعاملته كمتغير نوعي وتوليد فئات المقارنة المرجعية الصحيحة.

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

6.3 استخدام CategoricalDtype للتحكم الدقيق في التحويل

يمثل الصنف المتقدم CategoricalDtype الموجود في الوحدة pandas.api.types الأداة الهندسية الأكثر احترافية للتحكم الشامل في سلوك وتكوين النوع الفئوي. يتيح هذا الصنف تعريف نوع بيانات مخصص بالكامل يتضمن تحديد قائمة الفئات المسموحة بدقة بالغة وتحديد ما إذا كانت هذه الفئات تخضع لترتيب هرمي صارم أم لا.

يتم استخدام هذا الصنف عبر استيراده أولاً: from pandas.api.types import CategoricalDtype، ثم بناء كائن النوع المخصص مثل: size_type = CategoricalDtype(categories=['Small', 'Medium', 'Large', 'Extra Large'], ordered=True). بعد ذلك، يتم تمرير هذا الكائن المخصص مباشرة كمعامل داخل دالة التحويل: df['size'] = df['size'].astype(size_type).

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

7. إنشاء المتغيرات الفئوية المرتبة وغير المرتبة (Ordered vs Unordered)

7.1 المتغيرات الاسمية (Nominal) مقابل المتغيرات الترتيبية (Ordinal)

ينقسم علم القياس الإحصائي إلى مستويات قياس كلاسيكية، يأتي في مقدمتها المتغيرات الاسمية (Nominal Variables) والمتغيرات الترتيبية (Ordinal Variables). تمثل المتغيرات الاسمية فئات نوعية متكافئة لا يوجد بينها أي تفاضل كمي أو تراتبية طبيعية، مثل فصائل الدم (A, B, AB, O) أو الجنسيات أو ألوان السيارات؛ حيث لا يمكن القول إن الفصيلة A “أكبر من” أو “تسبق” الفصيلة B بأي مقياس منطقي.

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

تستجيب مكتبة Pandas لهذه التفرقة المنهجية عبر المعامل المنطقي ordered. فعندما يكون ordered=False (وهي الحالة الافتراضية في معظم دوال التحويل)، يُعامل المتغير كمتغير اسمي متكافئ. أما عند ضبط ordered=True، فإن Pandas يوثق الترتيب التراتبي للفئات بناءً على تسلسل ظهورها في مصفوفة categories، مما يفتح الباب لتطبيق العمليات الرياضية الترتيبية على هذه البيانات بأمان كامل.

7.2 عمليات المقارنة والفرز على المتغيرات المرتبة

عندما يُعرّف العمود كمتغير فئوي مرتب (Ordered Categorical)، تكتسب السلسلة إمكانيات برمجية استثنائية تحاكي المتغيرات الرقمية. يصبح بالإمكان استخدام كافة معاملات المقارنة الترتيبية المنطقية مثل الأصغر من (<)، والأصغر من أو يساوي (<=)، والأكبر من (>)، والأكبر من أو يساوي (>=) مباشرة على النصوص.

يتيح ذلك كتابة عبارات ترشيح أنيقة وبديهية؛ فعلى سبيل المثال، يمكن تصفية الموظفين ذوي الأداء المرتفع بكتابة الشرط المنطقي المباشر: df[df['performance'] >= 'Good']، وسيعيد Pandas كافة السجلات التي تقع في فئة “Good” أو الفئات الأعلى منها وفقاً للترتيب المعرف مسبقاً، دون الحاجة للرجوع إلى الأكواد الرقمية الأصلية.

كما تتجلى قوة المتغيرات المرتبة في عمليات الفرز؛ فعند استدعاء الدالة df.sort_values('education_level')، يقوم النظام بفرز الصفوف تصاعدياً وفقاً للتسلسل الهرمي للمراحل التعليمية (ابتدائي ثم ثانوي ثم جامعي) وليس وفقاً للترتيب الهجائي الأبجدي للأحرف الذي كان سيضع “ابتدائي” بعد “ثانوي”. علاوة على ذلك، تصبح الدوال الإحصائية مثل df['level'].min() و df['level'].max() صالحة للاستخدام لإرجاع أدنى وأعلى فئة مسجلة في العينة.

7.3 تغيير حالة الترتيب وإعادة ضبطه لاحقاً

توفر مكتبة Pandas عبر الملحق الفئوي المخصص .cat مجموعة من التوابع المرنة لتعديل حالة الترتيب أو إعادة صياغة التراتبية في أي مرحلة لاحقة من مراحل التحليل. إذا كان العمود فئوياً غير مرتب وأردنا ترقيته ليصبح مرتباً، يمكن استدعاء التابع المباشر df['col'] = df['col'].cat.as_ordered().

وعلى العكس من ذلك، إذا أردنا إلغاء الترتيب الهرمي ومعاملة الفئات كمتغيرات اسمية متكافئة، يمكن استدعاء التابع df['col'] = df['col'].cat.as_unordered(). يحمي هذا الإلغاء التحليل من إجراء مقارنات ترتيبية خاطئة إذا تبين أن المنطق النظري للدراسة لا يدعم التراتبية الهرمية بين تلك المجموعات.

وفي حال الرغبة في تعديل التسلسل الهرمي للفئات (مثلاً لعكس اتجاه الترتيب من التنازلي إلى التصاعدي أو تعديل موقع فئة مستحدثة)، يوفر Pandas الدالة المتخصصة df['col'] = df['col'].cat.reorder_categories(new_categories, ordered=True). يؤدي هذا التعديل إلى إعادة هيكلة البنية المنطقية للعمود فورياً وتحديث سلوك كافة عمليات الفرز والمقارنة اللاحقة دون التأثير على القيم الفعلية المخزنة في الصفوف.

8. معالجة المتغيرات الفئوية: إدارة الفئات والتعديل عليها (Categories Management)

8.1 استكشاف خصائص العمود الفئوي عبر الملحق .cat

تخصص مكتبة Pandas ملحقاً برمجياً حصرياً يُعرف باسم .cat accessor، وهو واجهة مخصصة تتيح للمحلل الوصول المباشر إلى كافة الخصائص البنيوية والوظائف الإدارية الخاصة بالبيانات الفئوية فقط، بصورة تماثل الملحق .str للنصوص والملحق .dt للتواريخ والأوقات.

يوفر هذا الملحق خصائص استكشافية حيوية؛ حيث تتيح الخاصية df['col'].cat.categories عرض مصفوفة الفئات المعتمدة رسمياً لهذا العمود، بينما تُظهر الخاصية df['col'].cat.ordered قيمة منطقية تحدد ما إذا كان العمود مرتباً أم لا. وتُعد الخاصية df['col'].cat.codes من أهم الخصائص المتاحة، حيث تكشف عن مصفوفة الأعداد الصحيحة التحتية التي يستخدمها Pandas داخلياً لتمثيل الفئات في الذاكرة.

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

8.2 إضافة فئات جديدة وإعادة تسمية الفئات الحالية

نظراً لأن الأعمدة الفئوية تفرض قيوداً صارمة على القيم المسموحة، فإن محاولة إسناد قيمة نصية جديدة غير مدرجة مسبقاً في قائمة الفئات ستؤدي حتماً إلى إطلاق خطأ برمجي صارم من نوع ValueError. ولإضافة قيم جديدة بأمان، يجب أولاً توسيع نطاق الفئات المعرفة باستخدام التابع df['col'] = df['col'].cat.add_categories(['New_Category'])، وبعدها يمكن إسناد القيمة الجديدة للصفوف دون أي اعتراض من النظام.

أما في سيناريوهات تنظيف البيانات وتوحيد المصطلحات، تبرز الحاجة إلى إعادة تسمية الفئات القائمة (مثلاً لتصحيح أخطاء إملائية أو ترجمة الفئات من لغة إلى أخرى). يوفر Pandas لهذه المهمة التابع df['col'] = df['col'].cat.rename_categories(new_names)، والذي يقبل إما قائمة بالأسماء الجديدة بنفس ترتيب الفئات القديمة، أو قاموساً تعيينياً يربط الاسم القديم بالاسم الجديد بدقة متناهية.

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

8.3 حذف الفئات غير المستخدمة وإزالة الفئات الفائضة

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

لتنظيف العمود وتطهير الذاكرة من هذه الفئات المهجورة، يوفر Pandas التابع فائق الأهمية df['col'] = df['col'].cat.remove_unused_categories(). يقوم هذا التابع بفحص الترددات الفعلية في البيانات وحذف أي فئة لا يقابلها أي سجل حقيقي، مما يعيد ضبط أبعاد العمود ويوفر المساحة الذاكرية ويحسن مخرجات النمذجة.

وعلاوة على ذلك، إذا رغب المحلل في إزالة فئة معينة عمداً وتحويل كافة قيمها القائمة في الجدول إلى قيم مفقودة (NaN)، يمكن استخدام التابع df['col'] = df['col'].cat.remove_categories(['Unwanted_Category']). كما يمكن استخدام التابع الشامل df['col'] = df['col'].cat.set_categories(new_list) لإعادة ضبط الفئات دفعة واحدة، حيث يقوم بإضافة الفئات الجديدة وإزالة الفئات المستبعدة وضبط الترتيب في خطوة واحدة حاسمة.

9. تحويل المتغيرات الفئوية لنمذجة التعلم الآلي: الترميز الأحادي والترتيبي

9.1 الترميز الأحادي باستخدام pd.get_dummies()

لا تستطيع معظم خوارزميات التعلم الآلي المعتمدة على الرياضيات الخطية والمصفوفات الحسابية (مثل الانحدار الخطي واللوجستي والشبكات العصبية) معالجة الفئات النوعية مباشرة بنصوصها. يتطلب ذلك تحويل المتغيرات الاسمية إلى تمثيل رقمي ثنائي عبر تقنية الترميز الأحادي (One-Hot Encoding)، حيث يتم تفكيك العمود الفئوي إلى عدة أعمدة وهمية ثنائية (Dummy Columns) تأخذ القيمة 1 عند تحقق الفئة و 0 عند غيابها.

توفر مكتبة Pandas الدالة القوية pd.get_dummies() لتنفيذ هذا التحويل الفوري بكفاءة عالية. تتعرف هذه الدالة تلقائياً على الأعمدة ذات النوع category وتقوم بترميزها دون المساس بالأعمدة الرقمية الأخرى، مما يوفر وقتاً كبيراً في إعداد مصفوفة الميزات (Feature Matrix).

ومن الناحية الإحصائية والرياضية، تتسبب إضافة كافة الأعمدة الوهمية في نشوء مشكلة الارتباط الخطي التام بين المتغيرات المستقلة (Multicollinearity)، وهو ما يُعرف في الأدبيات الإحصائية بفخ المتغيرات الوهمية (Dummy Variable Trap). لتفادي هذه المعضلة الحسابية، تتيح الدالة تفعيل المعامل drop_first=True، الذي يقوم بإسقاط العمود الوهمي للفئة الأولى تلقائياً واستخدامها كفئة مرجعية للمقارنة (Reference Category)، مما يضمن استقرار النماذج الإحصائية ودقة تقدير معاملاتها الرياضية.

9.2 الترميز الرقمي والترتيبي (Label & Ordinal Encoding)

في المقابل، تمثل النماذج المعتمدة على أشجار القرار وخوارزميات التعزيز التدرجي مثل XGBoost و LightGBM بيئة مثالية لاستقبال المتغيرات الترتيبية المشفرة عددياً (Ordinal / Label Encoding)، حيث تستطيع هذه الخوارزميات إجراء انقسامات هرمية فعالة على الأكواد العددية دون الحاجة لتوسيع أبعاد البيانات عبر الترميز الأحادي.

يمكن للمحلل استخراج الترميز الرقمي الداخلي لأي عمود فئوي في Pandas مباشرة وبمنتهى السرعة عبر استدعاء الخاصية df['cat_code'] = df['category_column'].cat.codes. تُسند هذه الخاصية لكل فئة عدداً صحيحاً يبدأ من 0 للمستوى الأدنى ويتزايد تتابعياً وفقاً لترتيب الفئات المعرف في العمود.

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

9.3 تجنب تسرب البيانات (Data Leakage) عند ترميز الفئات

يُمثل تسرب البيانات (Data Leakage) أحد أخطر الأخطاء المنهجية التي يقع فيها ممارسو علم البيانات عند إعداد المتغيرات الفئوية للتنبؤ. يحدث هذا التسرب عندما يتم تطبيق دوال الترميز أو حساب التقطيع الإحصائي (مثل pd.cut أو pd.get_dummies) على كامل مجموعة البيانات قبل تقسيمها إلى بيانات تدريب (Train Set) وبيانات اختبار (Test Set)، مما يؤدي إلى تسرب معلومات إحصائية وتوزيعية من بيانات الاختبار إلى نموذج التدريب، وتضخيم دقة التقييم بصورة مضللة.

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

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

10. تحسين استهلاك الذاكرة وسرعة المعالجة باستخدام البيانات الفئوية

10.1 دراسة مقارنة تفصيلية لاستهلاك الذاكرة (Memory Profiling)

لإدراك الحجم الفعلي للوفر الذاكري الذي يقدمه النوع الفئوي، يمكن إجراء تجربة قياسية برمجية (Benchmarking) عبر إنشاء إطار بيانات ضخم يحتوي على مليون سجل نصي يتضمن أسماء خمس قارات تتكرر باستمرار. عند فحص استهلاك الذاكرة لهذا العمود النصي بنوعه الافتراضي object باستخدام df.memory_usage(deep=True)، سنجد أنه يستهلك ما يقارب 60 إلى 80 ميجابايت من الذاكرة العشوائية.

وعند تطبيق التحويل الفوري df['continent'] = df['continent'].astype('category') وإعادة قياس الذاكرة العميقة، ينخفض الحجم المستهلك لنفس العمود إلى قرابة 1 ميجابايت فقط، محققاً نسبة توفير تتجاوز 98% من حجم الذاكرة المستهلكة. يعود هذا الانخفاض الهائل إلى استبدال مليون مؤشر كائن نصي ثقيل بمصفوفة مدمجة من الأعداد الصحيحة من نوع int8 التي تستهلك بايتاً واحداً فقط لكل صف.

ومع ذلك، توجد نقطة تعادل حسابية (Break-even Point) يجب على المهندس إدراكها؛ فإذا كان العمود يحتوي على بيانات نصوص فريدة بالكامل تقريباً (مثل معرفات الحسابات البنكية حيث نسبة التكرار تقترب من الصفر)، فإن التحويل إلى category سيضيف جدول فئات ضخم دون توفير في مصفوفة الأكواد، مما قد يؤدي في هذه الحالة النادرة إلى زيادة طفيفة في استهلاك الذاكرة بدلاً من خفضها.

10.2 تسريع عمليات التجميع (GroupBy) والتصفية

لا يقتصر تأثير استخدام المتغيرات الفئوية على الذاكرة الساكنة فحسب، بل يمتد بصورة دراماتيكية إلى سرعة المعالجة الديناميكية أثناء تنفيذ العمليات الحسابية والتحليلية. عند تنفيذ عمليات التجميع والدمج الإحصائي عبر الدالة df.groupby('category_col').mean()، تتفوق الأعمدة الفئوية بمراحل على الأعمدة النصية.

يرجع هذا التفوق الحسابي إلى أن محرك مكتبة Pandas الداخلي المكتوب بلغة C لا يحتاج إلى مقارنة الحروف الهجائية لكل نص وإجراء عمليات التجزئة النصية (String Hashing) المكلفة، بل ينفذ التجميع مباشرة على مصفوفة الأكواد الصحيحة المدمجة عبر خوارزميات الفرز العددي فائق السرعة، مما يقلل زمن التنفيذ إلى أجزاء من الثانية حتى مع ملايين الصفوف.

ومن المعاملات المفصلية في تسريع عمليات التجميع معامل observed داخل دالة groupby. عند ضبط observed=True، يقتصر التجميع الحسابي على الفئات الموجودة فعلياً في البيانات، بينما يؤدي ضبط observed=False إلى إظهار كافة الفئات المعرفة في categories حتى لو لم تكن تمتلك أي سجلات فعلية في الجدول، وهو خيار بالغ الأهمية عند توليد الجداول الإحصائية المتقاطعة للتقارير الرسمية لضمان عدم اختفاء الفئات الصفرية.

10.3 كفاءة حفظ وتحميل البيانات (I/O Performance)

تمتد كفاءة المتغيرات الفئوية لتشمل عمليات القراءة والكتابة من وإلى وسائط التخزين الدائمة (I/O Performance). عند تخزين إطارات البيانات في صيغ الملفات المسطحة التقليدية مثل CSV، يتم فقدان كافة الخصائص البنيوية للفئات، مما يجبر النظام على إعادة بناء الفئات واستهلاك وقت المعالجة من جديد عند كل عملية قراءة.

للحفاظ على هذه المكاسب البنيوية، يوصى بالاعتماد على صيغ التخزين الثنائية العمودية المتقدمة مثل Apache Parquet و Feather / Arrow. تدعم هذه الصيغ الحديثة تخزين البيانات الوصفية (Metadata) للمتغيرات الفئوية بصورة أصلية مدمجة، مما يعني حفظ مصفوفة الأكواد والفئات وترتيبها الداخلي مباشرة داخل بنية الملف التخزيني.

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

11. التعامل مع القيم المفقودة (Missing Values / NaN) في الأعمدة الفئوية

11.1 سلوك القيم المفقودة داخل البنية الفئوية لـ Pandas

تمتلك مكتبة Pandas نهجاً بنيوياً فريداً ومحكماً في التعامل مع القيم المفقودة (Missing Values / NaN) داخل الأعمدة الفئوية. في البنية الداخلية للذاكرة، لا تُعتبر القيمة المفقودة فئة مستقلة مدرجة داخل قائمة categories، بل يتم تمثيلها برمجياً في مصفوفة الأكواد التحتية codes بالعدد الصحيح -1.

يضمن هذا التمثيل المبتكر عدم شغل أي مساحة إضافية في جدول الفئات، كما يضمن استجابة العمود الفئوي بصورة متسقة مع كافة دوال فحص وتنقية البيانات المفقودة في Pandas مثل df.isnull() و df.isna()، والتي تعيد القيمة المنطقية True أمام أي سجل يحمل الكود -1.

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

11.2 طرق معالجة وتعويض القيم المفقودة (Imputation)

عند محاولة معالجة البيانات المفقودة في عمود فئوي عبر تقنيات التعويض (Imputation)، يقع العديد من المبرمجين في خطأ برمجي شائع عند محاولة استخدام الدالة fillna() لتعويض القيم الناقصة بنص جديد مثل “غير محدد” أو “Missing”. إذا لم يكن هذا النص مدرجاً مسبقاً في قائمة الفئات الرسمية للعمود، سيطلق Pandas فوراً الخطأ الشهير ValueError: Cannot setitem on a Categorical with a new category.

لتنفيذ عملية التعويض بصورة منهجية صحيحة، يجب اتباع مسار هندسي يتكون من خطوتين رئيستين: الخطوة الأولى هي إضافة الفئة الجديدة المستهدفة رسمياً إلى قائمة الفئات المعرفة عبر df['col'] = df['col'].cat.add_categories(['غير محدد'])؛ والخطوة الثانية هي تطبيق دالة التعويض بأمان كامل: df['col'] = df['col'].fillna('غير محدد').

وفي حال الرغبة في تعويض القيم المفقودة بالقيمة الأكثر تكراراً في العينة (Statistical Mode)، يمكن استخراج المنوال الإحصائي وتطبيقه مباشرة عبر الصيغة: mode_val = df['col'].mode()[0] ثم df['col'].fillna(mode_val, inplace=True)، وبما أن المنوال ينتمي حتماً إلى الفئات المعرفة مسبقاً، فإن هذه العملية تتم بنجاح فوري دون الحاجة لإضافة فئات جديدة.

11.3 تأثير القيم المفقودة على التحليلات والتجميع الإحصائي

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

وللحصول على رؤية شاملة ودقيقة تتضمن حجم الفقد، يجب دائماً تفعيل المعامل dropna=False داخل الدالة: df['col'].value_counts(dropna=False). ستقوم هذه الدالة بإظهار عدد القيم المفقودة (NaN) ونسبتها المئوية جنباً إلى جنب مع الفئات المعتمدة، وهو أمر بالغ الأهمية في تقارير الاستبيانات والمقاييس النفسية لتحديد معدلات عدم الاستجابة.

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

12. أفضل الممارسات والأخطاء الشائعة عند التعامل مع المتغيرات الفئوية في Pandas

12.1 الأخطاء الشائعة واستراتيجيات تصحيحها (Troubleshooting)

تتكرر مجموعة من الأخطاء البرمجية الشهيرة عند التعامل مع البيانات الفئوية في بايثون، ويساعد فهم أسبابها العميقة في كتابة أكواد قوية ومحصنة ضد الانهيار. يأتي في مقدمة هذه الأخطاء محاولة تعديل قيمة عنصر فردي في العمود الفئوي بقيمة نصية جديدة تماماً، مما يولد الخطأ المعروف ValueError: Cannot setitem...، وحله يكمن دائماً في استدعاء cat.add_categories() قبل الإسناد.

الخطأ الشائع الثاني هو TypeError عند محاولة مقارنة أو دمج عمودين فئويين يمتلكان فئات مختلفة أو ترتيباً غير متطابق. لحل هذه المعضلة عند دمج سلاسل فئوية مستقلة، توفر مكتبة Pandas الدالة المتقدمة from pandas.api.types import union_categoricals، والتي تقوم بتوحيد الفئات ودمجها بذكاء قبل إجراء عمليات الدمج الكبرى.

أما المشكلة الثالثة فترتبط بفقدان النوع الفئوي والرجوع التلقائي الصامت إلى نوع object عند تطبيق بعض دوال التحويل مثل df['col'].apply() أو df['col'].map(). ولتجنب هذا التدهور في الأداء، يفضل دائماً استخدام التوابع المخصصة المتاحة داخل الملحق .cat بدلاً من الدوال العامة، أو إعادة صب النوع صراحة بعد انتهاء المعالجة.

12.2 أفضل الممارسات الهندسية لكتابة كود نظيف وقابل للتوسع

لبناء أنظمة معالجة بيانات احترافية وقابلة للتوسع في بيئات العمل الحقيقية، يوصى باتباع حزمة من أفضل الممارسات الهندسية المعتمدة لدى خبراء البيانات. أولى هذه الممارسات هي التحديد المبكر والمسبق للأنواع الفئوية أثناء قراءة الملفات الضخمة من المصدر، وذلك عبر تمرير قاموس الأنواع لمعامل dtype داخل الدالة pd.read_csv('data.csv', dtype={'category_col': 'category'})، مما يمنع استهلاك الذاكرة الأولي أثناء مرحلة التحميل.

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

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

12.3 الخلاصة وخارطة الطريق لتطوير مهارات معالجة البيانات

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

  • استخدم astype('category') للتحويل السريع للأعمدة النصية والرقمية الموجودة مسبقاً ذات التكرار العالي.
  • استخدم CategoricalDtype عندما تحتاج إلى فرض فئات محددة وثابتة وترتيب صارم عبر بيئات متعددة.
  • استخدم pd.cut() لتقطيع المتغيرات الرقمية المستمرة بناءً على حدود وفترات عددية محددة وثابتة العرض.
  • استخدم pd.qcut() لتقسيم البيانات الرقمية بناءً على التوزيع التكراري والمئينات لضمان توازن حجم العينات.
  • استخدم ملحقات .cat لإدارة الفئات، وإضافة قيم جديدة، وحذف الفئات المهجورة لتنظيف مخرجات التحليل.
  • استخدم pd.get_dummies() مع drop_first=True لتهيئة المتغيرات الاسمية لنماذج الانحدار والتعلم الآلي.

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

References

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

looti, M. (2026, سبتمبر 2). كيفية إنشاء متغيرات فئوية في بانداس (مع أمثلة). عرب سايكلوجي. https://arabpsychology.com/how-to-create-categorical-variables-in-pandas-with-examples/
looti, Mohammed. “كيفية إنشاء متغيرات فئوية في بانداس (مع أمثلة).” عرب سايكلوجي, 2 سبتمبر 2026, https://arabpsychology.com/how-to-create-categorical-variables-in-pandas-with-examples/.
looti, Mohammed. “كيفية إنشاء متغيرات فئوية في بانداس (مع أمثلة).” عرب سايكلوجي. سبتمبر 2, 2026. https://arabpsychology.com/how-to-create-categorical-variables-in-pandas-with-examples/.