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

بانداس: كيفية تحديد الصفوف بين تاريخين


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

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

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

1. المفاهيم التأسيسية لإدارة السلاسل الزمنية وتصفية البيانات في مكتبة بانداس

1.1 أهمية تصفية البيانات الزمنية في تحليل البيانات المتقدم

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

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

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

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

1.2 البنية الهيكلية لبيانات السلاسل الزمنية داخل كائنات DataFrame

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

لتجاوز هذا القصور الهيكلي، توفر بانداس كائنات متخصصة ومصممة للتعامل مع الزمن، وفي مقدمتها كائن Timestamp الذي يمثل نقطة زمنية محددة بدقة فائقة، وكائن DatetimeIndex الذي يمثل مصفوفة مفهرسة من الطوابع الزمنية. يستند كائن Timestamp إلى المعيار القياسي datetime64[ns] الخاص بمكتبة NumPy، وهو ما يتيح تمثيل التواريخ والأوقات بدقة تصل إلى مستوى النانو ثانية، مما يوفر قدرة هائلة على تمثيل الأحداث فائقة السرعة والعمليات الحسابية المتناهية في الدقة على مدار عقود وقرون ممتدة زمنياً.

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

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

2. التهيئة المسبقة ومعالجة أنواع البيانات الزمنية باستخدام pd.to_datetime

2.1 تحويل الأعمدة النصية إلى أنواع زمنية قياسية

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

عند التعامل مع مجموعات بيانات تتسم بالتعقيد أو التباين في أساليب التوثيق، يصبح من الضروري ضبط المعامل format داخل الدالة pd.to_datetime. يؤدي التحديد الصريح لنمط التنسيق (مثل %Y-%m-%d %H:%M:%S) إلى تسريع عملية التحويل البرمجي بصورة دراماتيكية، وتجنب اللجوء إلى خوارزميات التخمين الاستدلالية البطيئة والمكلفة من حيث موارد المعالجة. علاوة على ذلك، يمنع التنسيق الصريح الالتباس الشهير والخلط المنهجي بين ترتيب الأيام والشهور، لاسيما عند معالجة التنسيقات الأمريكية (الشهر أولاً) والتنسيقات الأوروبية والبريطانية (اليوم أولاً).

تحتوي مجموعات البيانات الواقعية في كثير من الأحيان على مدخلات تالفة أو أخطاء كتابية تجعل من المستحيل تحويل بعض النصوص إلى تواريخ صحيحة. تتيح مكتبة بانداس إدارة هذه الحالات الاستثنائية بمرونة عبر المعامل errors؛ حيث يؤدي ضبطه على القيمة errors='coerce' إلى إجبار الدالة على تحويل القيم غير الصالحة إلى القيمة الزمنية المفقودة الخاصة ببانداس والمعروفة باسم NaT (Not a Time). تضمن هذه الاستراتيجية استمرار تنفيذ البرنامج ومنع توقفه المفاجئ، مع تمكين المحلل من رصد وتتبع السجلات التالفة ومعالجتها لاحقاً وفق قواعد تنظيف البيانات المعتمدة.

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

2.2 التحقق من صحة واكتمال البيانات الزمنية قبل التصفية

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

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

يعد التحقق من الاتساق الزمني والترتيب الرتيب للصفوف خطوة بالغة الأهمية لضمان كفاءة ودقة عمليات التصفية؛ وتحديداً عند استخدام تقنيات تقطيع الفهرس المتقدمة. يمكن استخدام الخاصية is_monotonic_increasing للتأكد من أن السلسلة مرتبة تصاعدياً من الماضي إلى الحاضر. في حال وجود اختلالات في الترتيب ناتجة عن تجميع ملفات متعددة أو تأخر وصول حزم البيانات، يجب استدعاء الدالة sort_values() أو sort_index() لإعادة فرض النظام الزمني الصارم على هيكل الجدول بأكمله.

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

3. الأسلوب الأساسي: استخدام الدالة Series.between لتحديد الصفوف

3.1 الصياغة العامة والتطبيق العملي لدالة between

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

تعتمد الصياغة العامة للدالة على تمرير تاريخ البداية وتاريخ النهاية كسلاسل نصية أو ككائنات زمنية قياسية بالشكل البرمجي التالي:

df[df['date_column'].between('start_date', 'end_date')]

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

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

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

3.2 مقارنة دالة between بالدوال المناظرة في لغات الاستعلام الأخرى

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

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

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

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

4. التحكم الدقيق في حدود النطاق الزمني عبر المعامل inclusive

4.1 تضمين أو استبعاد نقاط البداية والنهاية (both, neither, left, right)

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

القيمة الافتراضية لهذا المعامل في الإصدارات الحديثة هي inclusive='both'، وهي تقابل رياضياً الفترة المغلقة [start, end]. في هذا النمط، يتم تضمين كافة الصفوف التي تطابق تاريخ البداية وتاريخ النهاية تماماً ضمن النتائج المسترجعة؛ أي أن الشرط المكافئ منطقياً هو value >= start and value <= end. يُعد هذا النمط هو الأكثر استخداماً وشيوعاً في الاستعلامات اليومية التي تستهدف جلب كامل البيانات لتواريخ محددة متضمنة اليوم الأول والأخير بالكامل.

على النقيض من ذلك، يتيح استخدام القيمة inclusive='neither' إنشاء فترة مفتوحة بالكامل (start, end)، حيث يتم استبعاد السجلات التي تقع بالضبط على تاريخ البداية أو تاريخ النهاية، ويقتصر الاسترجاع فقط على القيم التي تقع بالكامل داخل الفاصل الزمني؛ وهو ما يكافئ منطقياً value > start and value < end. تُستخدم هذه الصياغة في التطبيقات التي تتطلب دراسة التغيرات الحادثة حصرياً بين حدثين دون احتساب القياسات المرتبطة بلحظات وقوع الأحداث نفسها.

أما لإنشاء الفترات نصف المفتوحة ونصف المغلقة، فإن المعامل يوفر القيمتين inclusive='left' و inclusive='right'. يمثل النمط left الفترة [start, end) التي تتضمن تاريخ البداية وتستبعد تاريخ النهاية (مكافئ لـ value >= start and value < end)، وهو النمط الرياضي والبرمجي القياسي المعتمد في معظم خوارزميات التقطيع الزمني والفهرسة الصفرية. بينما يمثل النمط right الفترة (start, end] التي تستبعد نقطة البداية وتتضمن نقطة النهاية (مكافئ لـ value > start and value < end)، وهو مفيد جداً في حساب الفروق التراكمية المحسوبة في نهاية كل دورة زمنية.

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

4.2 الآثار الإحصائية والتحليلية لاختيار حدود التضمين

إن الاختيار غير الدقيق لحدود التضمين قد يترتب عليه أخطاء منهجية جسيمة في التحليلات المتقدمة؛ وفي مقدمتها مشكلة العد المزدوج (Double Counting) عند تقسيم البيانات إلى نوافذ زمنية متتالية. فعند بناء نوافذ أسبوعية أو شهرية متجاورة، يؤدي تطبيق النمط المغلق inclusive='both' على كافة النوافذ إلى احتساب الملاحظات الواقعة في نقطة التقاطع بين فترتين مرتين، مما يؤدي إلى تضخيم زائف للمجاميع الإجمالية ومؤشرات الأداء التراكمية وتشويه النتائج النهائية.

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

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

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

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

5.1 الجمع بين الشروط باستخدام المؤثرات البوليانية (& و |)

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

تتم الصياغة الأساسية للشروط المركبة التي تحدد نطاقاً زمنياً محصوراً بين تاريخين عبر استخدام مؤثر العطف المنطقي الثنائي المتجه & على النحو التالي:

df[(df['date_column'] >= 'start_date') & (df['date_column'] <= 'end_date')]

من الضروري جداً التأكيد على الإلزامية الصارمة لاستخدام الأقواس الدائرية (...) حول كل تعبير شرطي منفصل. يرجع ذلك إلى قواعد أسبقية العمليات في بايثون؛ حيث يتمتع المؤثر البولياني الثنائي & بأولوية تنفيذ أعلى من معاملات المقارنة الرياضية (مثل >= و <=). وبدون استخدام الأقواس، ستقوم بايثون بمحاولة تقييم التعبير الأوسط أولاً مما يتسبب في أخطاء بناء فادحة من نوع TypeError أو ValueError.

تفتح هذه المنهجية الباب واسعاً لبناء نطاقات زمنية متعددة وغير متصلة داخل نفس الاستعلام عبر استخدام مؤثر الفصل المنطقي | (OR). على سبيل المثال، يمكن للمحلل استخراج السجلات التي وقعت في الربع الأول من عام معين بالتزامن مع السجلات التي وقعت في الربع الأول من العام الذي يليه، وذلك لدراسة المقارنات السنوية المباشرة (Year-over-Year) في استعلام برمجي موحد وعالي الكفاءة.

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

5.2 المقارنة الرياضية والمنطقية بين الأساليب الشرطية ودالة between

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

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

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

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

6. التصفية المعتمدة على الفهرس الزمني (DatetimeIndex والتقطيع بـ .loc)

6.1 إعداد الفهرس الزمني واستخدام التقطيع الجزئي للسلاسل (Label Slicing)

تمتلك مكتبة بانداس ميزة تصميمية فريدة تجعلها تتفوق على معظم مكتبات معالجة البيانات الأخرى، وتتمثل في دعمها الأصيل للفهارس المعتمدة على التسميات الزمنية من خلال كائن DatetimeIndex. عندما يتم تعيين عمود التاريخ والوقت كفهرس رسمي للجدول باستخدام الدالة set_index('date_column')، يتحول هيكل البيانات بالكامل إلى سلسلة زمنية حقيقية مفهرسة ومحسنة داخلياً لإجراء عمليات البحث والتقطيع اللحظي.

يتيح هذا التحول الهيكلي استخدام المعامل المرجعي المباشر df.loc[…] لإجراء عمليات التقطيع الزمني (Slicing) بأسلوب يضاهي تقطيع المصفوفات والقوائم التقليدية في لغة بايثون. تتم عملية التصفية حينها عبر كتابة المقطع الزمني الفاصل بين نقطتي البداية والنهاية بالشكل البرمجي التالي:

df.loc['start_date':'end_date']

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

تتجلى القوة المذهلة للتقطيع باستخدام .loc في دعمه لخاصية الفهرسة الجزئية للتواريخ (Partial String Indexing). تتيح هذه الخاصية للمطورين تحديد نطاقات زمنية واسعة دون الحاجة إلى تحديد اليوم أو الساعة أو الدقيقة بدقة؛ فعلى سبيل المثال، يمكن كتابة df.loc['2023-01':'2023-06'] لاستخراج كافة البيانات الممتدة من أول دقيقة في شهر يناير 2023 وحتى آخر ثانية في شهر يونيو 2023 تلقائياً وبشكل ضمني، حيث تدرك بانداس بذكاء الدقة الزمنية المطلوبة وتقوم بتوسيع حدود البحث لتشمل كامل الفترة المحددة.

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

6.2 التقطيع الزمني الجزئي واختيار البيانات عالية الدقة

يمتد دعم بانداس للتقطيع الزمني الجزئي ليشمل البيانات المسجلة بترددات زمنية فائقة الدقة، مثل البيانات المسجلة على مستوى الساعات، الدقائق، الثواني، والمللي ثانية. يتيح ذلك للباحثين في مجالات التداول الخوارزمي عالي التردد، أو مراقبة إنترنت الأشياء (IoT) والأنظمة الصناعية، استخراج نوافذ زمنية محددة بدقة متناهية عبر صياغة نصية طبيعية مثل df.loc['2023-10-01 09:30:00':'2023-10-01 16:00:00']، مما يسهل عزل ساعات جلسة التداول أو فترات تشغيل المعدات بدقة متناهية.

من المهم التمييز المفاهيمي والتقني بين التقطيع المعتمد على التسميات الزمنية عبر .loc والتقطيع المعتمد على المواقع العددية عبر المعامل الموضعي .iloc. يعتمد .iloc حصرياً على الأرقام الترتيبية للصفوف في الذاكرة (0, 1, 2, …) ولا يفهم الدلالات الزمنية للتواريخ. في حال الرغبة في استخدام المواقع العددية لتصفية فترات زمنية، يجب أولاً تحويل التواريخ إلى مواقع ترتيبية باستخدام دوال الفهرسة مثل index.get_slice_bound()، مما يجعل .loc الخيار الأكثر ملاءمة ومباشرة للاستعلامات الزمنية المتخصصة.

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

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

7. استخدام دالة الاستعلام DataFrame.query لتصفية النطاقات الزمنية

7.1 بناء التعبيرات النصية داخل دالة query لتحديد التواريخ

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

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

df.query('"start_date" <= date_column <= "end_date"')

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

من أهم المزايا البرمجية التي توفرها دالة query هي القدرة على استدعاء المتغيرات المعرفة مسبقاً في بيئة العمل المحلية أو العامة عبر استخدام الرمز الخاص @ قبل اسم المتغير. يتيح ذلك كتابة تعليمات ديناميكية وقابلة لإعادة الاستخدام؛ مثل تعريف متغيرات البداية والنهاية في كود خارجي وتمريرها مباشرة داخل السلسلة النصية للاستعلام بالشكل: df.query('@start <= date_column <= @end')، مما يعزز من مرونة الأكواد ويجعلها مهيأة للتكامل داخل الدوال والأنظمة المؤتمتة.

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

7.2 مزايا ومحددات استخدام دالة query في المشاريع الإنتاجية

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

ومع ذلك، تواجه دالة query بعض المحددات المنهجية التي يجب مراعاتها عند تصميم الأنظمة الإنتاجية الحساسة. يتمثل المحدد الأول في أن الاستعلامات يتم تمريرها كسلاسل نصية، مما يعني أن اكتشاف الأخطاء البرمجية والإملائية في أسماء الأعمدة أو الشروط لا يتم في مرحلة التصريف والتحليل الأولي للشفرة (Compile-time / Linting)، بل يظهر فقط أثناء وقت التشغيل الفعلي (Runtime)، مما يفرض ضرورة تغطية هذه الاستعلامات باختبارات وحدة برمجية شاملة وصارمة.

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

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

8. التعامل مع الطوابع الزمنية الدقيقة والساعات والمناطق الزمنية

8.1 إدارة الساعات والدقائق والثواني في استعلامات النطاق اليومي

تُمثل إدارة الساعات والدقائق والثواني أحد أكثر المصادر شيوعاً للأخطاء المنطقية والتحليلية الخفية عند تصفية البيانات الزمنية اليومية في مكتبة بانداس. يرجع السبب الجذري لهذه الإشكالية إلى أن تحويل النصوص التي تمثل تواريخ مجردة (مثل '2023-01-31') إلى طوابع زمنية قياسية يؤدي تلقائياً وبشكل افتراضي إلى ضبط الوقت عند منتصف الليل تماماً؛ أي عند الساعة 00:00:00. يؤدي هذا السلوك الضمني إلى استبعاد كافة السجلات التي وقعت خلال نفس اليوم المستهدف ولكن في ساعات تالية (مثل الساعة العاشرة صباحاً أو الخامسة مساءً)، نظراً لأنها تعتبر رياضياً أكبر من الطابع الزمني المرجعي للبداية الصفرية لليوم.

للتغلب على هذه المعضلة وضمان اشتمال الاستعلام على كامل أحداث اليوم الأخير في النطاق المحدد، توجد عدة استراتيجيات برمجية وهندسية راسخة. تتمثل الاستراتيجية الأولى في الضبط اليدوي الصريح لحدود النهاية الزمنية لتشمل آخر لحظة في اليوم المستهدف عبر تمرير الوقت كاملاً بالشكل: '2023-01-31 23:59:59.999999'. تضمن هذه الصياغة الدقيقة احتواء كافة الأحداث اليومية حتى مستوى الميكروثانية والنانو ثانية، مما يمنع تسرب أي صفوف أو فقدان غير مقصود للملاحظات المسجلة في أواخر ساعات اليوم.

أما الاستراتيجية المنهجية الثانية، فتعتمد على تطبيق التجريد الزمني وتطبيع البيانات (Normalization) قبل إجراء المقارنات. توفر مكتبة بانداس توابع متخصصة مثل Series.dt.normalize() و Series.dt.floor('D')، والتي تقوم بتصفير مكونات الوقت بالكامل وضبطها جميعاً عند 00:00:00 مع الحفاظ الكامل على دقة التاريخ اليومي. يتيح ذلك إجراء مقارنات يومية متجانسة وعادلة بين التواريخ دون أدنى تأثر بفروق الساعات والدقائق المسجلة في السجلات الفردية.

يتيح ملحق الخصائص الزمنية Series.dt أيضاً استخراج المكونات اليومية الصرفة ككائنات تاريخ مجردة عبر الخاصية Series.dt.date. مع ذلك، يجب الحذر عند استخدام هذه الخاصية للمقارنات المباشرة في مجموعات البيانات الضخمة؛ نظراً لأن تحويل الطوابع الزمنية المحسنة إلى كائنات datetime.date المجردة في بايثون يُسقط التخزين المتجه منخفض المستوى ويعيد البيانات إلى نوع object البطيء في الذاكرة، مما يجعل استخدام normalize() الخيار الهندسي الأمثل من حيث الحفاظ على أعلى مستويات الأداء الحسابي.

8.2 تصفية البيانات متعددة المناطق الزمنية (Timezone-Aware Data)

تفرض العولمة وتوزيع البنى التحتية السحابية تحديات معقدة عند تصفية البيانات التي تم جمعها عبر مناطق جغرافية متباينة. تُميز مكتبة بانداس بدقة متناهية بين كائنات التواريخ الساذجة (Timezone-Naive Objects) التي تفتقر إلى أي معلومات عن المنطقة الزمنية، وكائنات التواريخ الواعية (Timezone-Aware Objects) التي ترتبط صراحة بمنطقة زمنية محددة مثل UTC أو Asia/Riyadh أو America/New_York مستندة إلى قاعدة بيانات الهيئة الدولية لتخصيص الأرقام والأسماء (IANA Time Zone Database).

تُطلق مكتبة بانداس خطأً برمجياً حاسماً من نوع TypeError عند محاولة تنفيذ أي مقارنة منطقية أو تصفية نطاق بين كائن تاريخ ساذج وكائن تاريخ واعٍ بالمنطقة الزمنية. لتفادي هذه الإشكالية، يجب تطبيق التوطين والتحويل الصريح للمناطق الزمنية كخطوة معالجة مسبقة وإلزامية باستخدام الدالتين المخصصتين tz_localize() لإسناد المنطقة الزمنية للبيانات الساذجة، و tz_convert() لتحويل البيانات الواعية من منطقة زمنية إلى أخرى وفق المتطلبات التحليلية المعتمدة.

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

علاوة على ذلك، تلعب الإدارة الصارمة للمناطق الزمنية دوراً حاسماً في معالجة الآثار المعقدة لظاهرة التوقيت الصيفي (Daylight Saving Time – DST). إذ يؤدي الانتقال السنوي للتوقيت الصيفي إلى حدوث انقطاعات زمنية (تخطي ساعة كاملة في الربيع) أو تكرارات زمنية غامضة (تكرار نفس الساعة في الخريف). تضمن هياكل بانداس الواعية بالمنطقة الزمنية التعامل الخوارزمي السليم مع هذه الانزياحات الزمنية المعقدة، وتضمن استخراج النطاقات الزمنية الممتدة عبر فترات التغيير دون أي انقطاع حسابي أو تضارب في ترتيب الأحداث المتزامنة.

9. التقييم الحسابي ومقارنة الأداء والكفاءة بين أساليب التصفية

9.1 قياس زمن التنفيذ (Benchmarking) عبر مجموعات بيانات متفاوتة الحجم

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

تُظهر نتائج الاختبارات الحسابية فروقاً واضحة في سرعة التنفيذ بين الأساليب الرئيسية المتاحة:

  • تقطيع الفهرس الزمني عبر .loc: يتصدر قائمة الأداء الحسابي بأقل زمن تنفيذ ممكن، بشرط أن يكون الفهرس مرتباً بشكل رتيب وصارم. يرجع هذا التفوق إلى استخدام خوارزميات البحث الثنائي في هيكل C الداخلي التي تتيح العثور على حدود النطاق وتحديده بزمن لوغاريتمي من رتبة O(log n) دون الحاجة إلى فحص ومسح كافة عناصر الجدول بالكامل.
  • الدالة المدمجة Series.between: تقدم أداءً ممتازاً ومستقراً جداً، حيث تُنفذ عمليات المقارنة المتجهة بالكامل في لغة C بزمن خطي O(n). تتفوق الدالة قليلاً على المقارنات المنطقية المباشرة في بعض البيئات نظراً لتقليل عمليات إنشاء الكائنات البوليانية الوسيطة في الذاكرة.
  • المقارنات المنطقية المباشرة (&): تحقق سرعات متقاربة جداً مع دالة between وتعمل بزمن خطي O(n)، لكنها قد تستهلك وقتاً إضافياً طفيفاً في معالجة الدمج البولياني المتعدد عبر مصفوفات الأقنعة المنطقية الوسيطة.
  • دالة الاستعلام DataFrame.query: تُظهر أداءً فائق التميز مع مجموعات البيانات الضخمة (ملايين الصفوف) بفضل تسريع محرك NumExpr، بينما قد تظهر بطئاً نسبياً مع مجموعات البيانات الصغيرة جداً نظراً للوقت الإضافي المستغرق في إعراب وتحليل التعبير النصي للاستعلام قبل تنفيذه.

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

9.2 استهلاك الذاكرة وتأثير العمليات الموضعية (In-place Operations)

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

لتخفيض الضغط على الذاكرة، يُفضل تجنب التوليد المتعدد للنسخ الوسيطة غير الضرورية والاعتماد على الأقنعة المباشرة داخل المعامل الفهرسي. كما يُنصح بشدة بتحسين وتخفيض دقة الأنواع الزمنية عند عدم الحاجة إلى الدقة المتناهية؛ فعلى سبيل المثال، يتيح التحول من دقة النانو ثانية datetime64[ns] إلى دقة المللي ثانية datetime64[ms] أو الثواني datetime64[s] في الإصدارات الحديثة من بانداس تقليص حجم الأعمدة الزمنية في الذاكرة بنسب ملحوظة دون المساس بسلامة التحليلات اليومية والشهرية.

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

10. التعامل مع القيم المفقودة والشواذ أثناء التصفية الزمنية

10.1 سلوك دوال التصفية مع القيم الزمنية المفقودة (NaT)

تُمثل القيم المفقودة في الأعمدة الزمنية، والتي تُرمز لها مكتبة بانداس بكائنات NaT، حالة استثنائية تتطلب فهماً عميقاً لسلوكيات المقارنة المنطقية في لغة بايثون ومكتبة بانداس. تتبع كائنات NaT القواعد الصارمة للمنطق ثلاثي القيم (Three-Valued Logic)؛ حيث يتم تقييم أي مقارنة رياضية أو منطقية مباشرة مع القيمة المفقودة (سواء باستخدام ==، >، <، أو >=) بالقيمة المنطقية False دائماً وبشكل قطعي.

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

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

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

10.2 معالجة الفجوات الزمنية والبيانات غير المنتظمة

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

توفر مكتبة بانداس الدالة المتقدمة asfreq لاكتشاف وتحديد الفترات الزمنية المفقودة ضمن النطاق المختار. تتيح هذه الدالة فرض تردد زمني منتظم (مثل تردد يومي ‘D’ أو ساعي ‘H’) على الفهرس الزمني للجدول، مما يؤدي إلى توليد صفوف فارغة تحمل القيمة NaN أو NaT في كافة المواقع التي غابت فيها التسجيلات الفعلية، وهو ما يمنح المحلل خريطة واضحة ودقيقة لحجم ومواقع الفجوات الزمنية داخل الفترة المصفاة.

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

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

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

11.1 دراسة حالة 1: تصفية بيانات المعاملات المالية والمبيعات

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

لتنفيذ هذه المهمة بدقة، يتم استخدام الدالة Series.between مع ضبط المعامل inclusive='both' وتحديد الحدود الزمنية بالساعات والدقائق والثواني لتغطية آخر ثانية من اليوم الأخير في الربع المالي. يتيح هذا الاستخراج الدقيق عزل المعاملات التجارية المكتملة وحساب المقاييس الإحصائية الجوهرية مثل إجمالي حجم البضائع المباعة (GMV)، وصافي الأرباح، ومتوسط قيمة المعاملة الواحدة خلال تلك النافذة المحددة دون أي تداخل مع مبيعات الفترات اللاحقة.

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

11.2 دراسة حالة 2: تحليل سجلات الخوادم والأحداث المتزامنة (Log Analysis)

تتعامل فرق هندسة الموثوقية (Site Reliability Engineering – SRE) وأمن المعلومات يومياً مع مليارات الأسطر من سجلات الخوادم والأنظمة الموزعة (Server Logs) التي تسجل الأحداث والطلبات البرمجية بدقة المللي ثانية والميكروثانية. عند وقوع حادث أمني أو انقطاع مفاجئ في الخدمة، يصبح التحدي الأساسي هو عزل السجلات البرمجية المنشأة بدقة متناهية خلال النافذة الزمنية للحادث لتحديد السبب الجذري للعطل (Root Cause Analysis).

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

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

11.3 دراسة حالة 3: معالجة البيانات الصحية والتجارب السريرية

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

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

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

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

12.1 تجنب تحذير التعديل على نسخة SettingWithCopyWarning

يُعد التحذير الشهير SettingWithCopyWarning أحد أكثر التحذيرات إرباكاً للمطورين المبتدئين والمتمرسين على حد سواء في مكتبة بانداس. يظهر هذا التحذير عندما يحاول المبرمج تعديل أو إسناد قيم جديدة لصفوف تم استخراجها وتصفيتها عبر شروط النطاقات الزمنية باستخدام الفهرسة المتسلسلة (Chained Indexing)، مثل كتابة: df[df['date'].between(start, end)]['column'] = value.

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

لتجنب هذا التحذير البرمجي وضمان سلامة تعديل البيانات، توجد قاعدتان هندسيتان أساسيتان يجب الالتزام بهما بدقة:

  • استخدام التابع الصريح للنسخ .copy(): إذا كان الهدف هو إنشاء جدول بيانات جديد ومستقل يحتوي على الصفوف المصفاة زمنياً لإجراء تحليلات وتعديلات منفصلة عليه، يجب استدعاء التابع copy() صراحة بعد عملية التصفية بالشكل: filtered_df = df[df['date'].between(start, end)].copy(). يضمن ذلك تخصيص كتلة ذاكرة جديدة تماماً ويمنع أي تحذيرات برمجية لاحقة.
  • الإسناد الآمن عبر .loc: إذا كان الهدف هو تعديل قيم معينة داخل الجدول الأصلي نفسه للصفوف التي تقع ضمن النطاق الزمني المحدد، يجب استخدام الإسناد المباشر والموحد عبر .loc بالشكل: df.loc[df['date'].between(start, end), 'target_column'] = new_value. تُنفذ هذه الصياغة عملية البحث والتعديل في خطوة ذرية واحدة ومباشرة في الذاكرة دون أي وسائط مؤقتة.

12.2 كتابة تعليمات برمجية قابلة للصيانة وإعادة الاستخدام

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

يُنصح بشدة بالاعتماد على التلميحات النوعية (Type Hinting) في بايثون لتوثيق الدوال المسؤولة عن تصفية التواريخ. يتيح استخدام الأنواع الصريحة مثل pd.Timestamp و pd.DataFrame و Union[str, datetime] لأدوات التحليل الاستاتيكي ومحررات الأكواد الحديثة التحقق المسبق من صحة الأنواع الممررة ومنع الأخطاء الشائعة الناتجة عن تمرير كائنات نصية غير متوافقة أثناء استدعاء الدوال في بيئات الإنتاج.

علاوة على ذلك، يجب بناء منظومة متكاملة من اختبارات الوحدة البرمجية (Unit Tests) باستخدام أطر العمل المعيارية مثل pytest للتحقق المنهجي من سلامة شروط التصفية الزمنية. يجب أن تغطي هذه الاختبارات كافة الحالات الحدية الحرجة (Edge Cases)؛ مثل اختبار سلوك الدوال عند تمرير تواريخ خارج نطاق البيانات المتاحة، واختبار سلوك التضمين والاستبعاد عند نقاط البداية والنهاية، والتحقق من صحة التعامل مع الصفوف التي تحتوي على قيم مفقودة NaT أو مناطق زمنية متباينة.

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

خاتمة

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

بدءاً من التحويل الهيكلي الصريح باستخدام pd.to_datetime، مروراً بالاستخدام الأنيق للدالة Series.between والتحكم الدقيق في حدود النطاق عبر المعامل inclusive، ووصولاً إلى التقطيع المباشر عالي السرعة باستخدام DatetimeIndex و .loc، واستغلال محركات التقييم السريع عبر DataFrame.query؛ يتضح أن مكتبة بانداس تقدم منظومة برمجية متكاملة تتناسب مع كافة سيناريوهات البيانات ومستويات التعقيد الحسابي.

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

References

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

looti, M. (2026, سبتمبر 2). بانداس: كيفية تحديد الصفوف بين تاريخين. عرب سايكلوجي. https://arabpsychology.com/pandas-how-to-select-rows-between-two-dates/
looti, Mohammed. “بانداس: كيفية تحديد الصفوف بين تاريخين.” عرب سايكلوجي, 2 سبتمبر 2026, https://arabpsychology.com/pandas-how-to-select-rows-between-two-dates/.
looti, Mohammed. “بانداس: كيفية تحديد الصفوف بين تاريخين.” عرب سايكلوجي. سبتمبر 2, 2026. https://arabpsychology.com/pandas-how-to-select-rows-between-two-dates/.