كيفية استخراج الأرقام من سلسلة نصية في SAS
تُعد معالجة البيانات النصية غير المهيكلة واستخلاص القيم العددية منها إحدى أهم الركائز الأساسية في هندسة البيانات والتحليل الإحصائي المتقدم باستخدام نظام التحليل الإحصائي (SAS Institute). في الواقع العملي، نادراً ما تأتي البيانات الخام بصيغ رقمية نقية وجاهزة للتحليل الفوري؛ إذ غالباً ما تتداخل الأرقام مع النصوص، والرموز، والبادئات، واللاحقات الوصفية داخل حقل واحد نتيجة أخطاء الإدخال اليدوي، أو طبيعة الأنظمة المصدرية القديمة التي تدمج المعرفات ورموز العمليات في حقول نصية مركبة. إن استخراج هذه الأرقام وتحويلها إلى متغيرات كمية صالحة للتحليل الرياضي يمثل الخطوة الفاصلة بين البيانات الأولية المشوبة بالشوائب والمعلومات الدقيقة القابلة للاستخدام في النمذجة التنبؤية واتخاذ القرارات الاستراتيجية.
تتيح بيئة برمجيات SAS ترسانة متكاملة من الأدوات والدوال البرمجية التي تتباين في درجة تعقيدها ومرونتها، بدءاً من الدوال الحرفية البسيطة والفعالة مثل دالة الضغط COMPRESS المدعومة بالمعدلات الوظيفية (Modifiers)، وصولاً إلى محركات التعابير النمطية المتقدمة المبنية على لغة بيرل (Perl Regular Expressions – PRX)، ودوال التقطيع الموضعي مثل SCAN وSUBSTR. تتطلب كل منهجية فهماً عميقاً لآليات إدارة الذاكرة، وطبيعة التمييز الصارم بين الأنواع البيانية النصية (Character) والرقمية (Numeric) داخل محرك معالجة البيانات (DATA Step)، وذلك لضمان أعلى درجات الدقة وتفادي أي تشويه قد يلحق بالقيم الرياضية المستخلصة كفقدان الإشارات السالبة أو الفواصل العشرية.
يهدف هذا الدليل المرجعي الشامل إلى تقديم دراسة معمقة وتطبيقية لكافة الاستراتيجيات المتاحة لاستخراج الأرقام من السلاسل النصية في بيئة SAS. سنستعرض عبر اثني عشر محوراً تفصيلياً الآليات النظرية والبرمجية، والتحديات التقنية الشائعة، وكيفية التعامل مع الحالات الشاذة، بالإضافة إلى تقنيات تحسين الأداء في مجموعات البيانات الضخمة وبناء وحدات ماكرو قابلة لإعادة الاستخدام، مما يمنح محللي البيانات والمهندسين الإحصائيين مرجعاً متكاملاً لإتقان هذه المهارة الحيوية في خطوط أنابيب تنظيف البيانات.
- 1. مقدمة شاملة لمعالجة السلاسل النصية واستخراج الأرقام في بيئة SAS
- 2. الآلية الأساسية: استخدام دالة COMPRESS مع المعدِّلات لاستخراج الأرقام
- 3. تطبيق عملي: استخراج الأرقام من المعرفات ورموز المقررات الأكاديمية
- 4. التعامل مع الرموز الخاصة والمسافات البيضاء أثناء استخراج الأرقام
- 5. استخدام التعابير النمطية (Perl Regular Expressions) للاستخراج المتقدم
- 6. تحويل السلسلة النصية المستخرجة إلى متغير رقمي حقيقي باستخدام دالة INPUT
- 7. استخراج الأرقام باستخدام دوال الموقع والتقطيع (SCAN و SUBSTR و FIND)
- 8. معالجة الأرقام العشرية والكسور والإشارات السالبة في السلاسل النصية
- 9. إدارة الحالات الاستثنائية والقيم المفقودة أثناء معالجة النصوص
- 10. تحسين كفاءة المعالجة والأداء الحسابي في مجموعات البيانات الضخمة
- 11. مقارنة شاملة بين مختلف منهجيات استخراج الأرقام في SAS
- 12. أفضل الممارسات البرمجية وبناء دوال ماكرو (SAS Macros) قابلة لإعادة الاستخدام
- References
1. مقدمة شاملة لمعالجة السلاسل النصية واستخراج الأرقام في بيئة SAS
1.1 أهمية تنظيف البيانات النصية واستخراج المتغيرات الرقمية في التحليل الإحصائي
تمثل عملية تنظيف البيانات النصية واستخلاص المتغيرات الرقمية منها حجر الزاوية في إعداد البيانات للتحليل الإحصائي وبناء النماذج التنبؤية المتقدمة. في كثير من الأحيان، تحتوي البيانات المسترجعة من الأنظمة التشغيلية، وسجلات قواعد البيانات الطبية، وحسابات التجارة الإلكترونية، على بيانات مختلطة تتضمن قيماً كمية مغلفة داخل سلاسل نصية وصفية، مثل تسجيل المقادير الدوائية مصحوبة بوحدات القياس (مثل 500mg) أو معرفات المعاملات المالية المدمجة مع رموز العملات. إذا لم يتم عزل هذه القيم الرقمية بدقة وتجريدها من المحتويات النصية المحيطة بها، فإن الخوارزميات الإحصائية ونماذج التعلم الآلي ستتعامل معها كمتغيرات فئوية غير قابلة للحساب الرياضي، مما يؤدي إلى إهدار معلومات كمية بالغة الأهمية أو تشويه أبعاد فضاء الخصائص (Feature Space).
علاوة على ذلك، فإن تحويل البيانات الأكاديمية والمهنية المختلطة إلى مدخلات كمية قياسية يسهم في رفع كفاءة التحليل الإحصائي الوصفي والاستدلالي. على سبيل المثال، في الدراسات الاجتماعية والاقتصادية، قد يُسجل الدخل أو سنوات الخبرة كنصوص تتضمن نصوصاً توضيحية أو فواصل زمنية. إن استخراج القيم الرقمية الدقيقة يتيح حساب المتوسطات الحسابية، والانحرافات المعيارية، ومصفوفات الارتباط بدقة متناهية، ويحول دون استبعاد السجلات التي تحتوي على بيانات صالحة ولكنها غير منسقة. إن سلامة المؤشرات النهائية المستخرجة من نماذج الانحدار الخطي أو اللوجستي تعتمد بالدرجة الأولى على نقاء المتغيرات الرقمية الداخلة في التحليل وخلوها من التداخلات النصية المشوهة للمقاييس الكمية، وهو ما يبرز الأهمية القصوى لتطوير مسارات تنظيف آلية وموثوقة داخل بيئة SAS Documentation.
1.2 الفروق الجوهرية بين البيانات النصية (Character) والرقمية (Numeric) في SAS
تتميز بنية نظام SAS بالصرامة الشديدة فيما يتعلق بالتمييز بين نوعين أساسيين فقط من المتغيرات: المتغيرات النصية (Character Variables) والمتغيرات الرقمية (Numeric Variables). تُخزن المتغيرات النصية في SAS كسلسلة من البايتات ذات طول ثابت يتم تحديده مسبقاً، وتكون محاذاة القيم النصية إلى جهة اليسار بشكل افتراضي مع ملء المساحات المتبقية بفراغات بيضاء (Trailing Blanks). في المقابل، تُخزن كافة المتغيرات الرقمية في بيئة SAS كأرقام عشرية ذات دقة مزدوجة بالفاصلة العائمة (Double-Precision Floating-Point) باستهلاك افتراضي يبلغ 8 بايت من الذاكرة، بغض النظر عما إذا كان الرقم يمثل عدداً صحيحاً صغيراً أو كسراً عشرياً معقداً، وتكون محاذاة القيم الرقمية نحو اليمين.
ينشأ عن هذا التباين الهيكلي قيود صارمة على العمليات الحسابية والمنطقية؛ إذ لا يسمح محرك SAS بإجراء أي عمليات حسابية مباشرة، كالجمع والضرب أو تطبيق الدوال الإحصائية، على المتغيرات المعرفة كبيانات نصية، حتى لو كانت محتويات تلك السلسلة النصية تتكون ظاهرياً من أرقام فقط (مثل السلسلة “12345”). عند محاولة إجراء عملية حسابية على متغير نصي دون معالجة مسبقة، يلجأ محرك خطوة البيانات (DATA Step) إلى إجراء تحويل تلقائي ضمني (Implicit Type Conversion)، وهو ما يتسبب في إطلاق رسائل تحذيرية في سجل النظام (SAS Log) ويؤدي في كثير من الأحيان إلى استهلاك غير مبرر لموارد المعالجة أو حدوث أخطاء جسيمة إذا احتوت السلسلة على رموز غير متوقعة. لذلك، تستلزم استراتيجيات المعالجة الاحترافية عزل الأرقام من النصوص أولاً، ثم إجراء تحويل صريح وواضح (Explicit Conversion) لنوع البيانات لتأمين استقرار الكود وسلامة النتائج.
1.3 التحديات التقنية الشائعة في معالجة السلاسل النصية غير المنظمة
تواجه عمليات استخراج الأرقام من السلاسل النصية غير المنظمة في بيئة SAS جملة من التحديات التقنية المعقدة الناجمة عن عدم اتساق تنسيق البيانات المدخلة. يتمثل التحدي الأول في تداخل الرموز الأبجدية مع الأرقام دون وجود فواصل قياسية منتظمة تفصل بينهما، كما هو الحال في الرموز التعريفية للأجهزة (مثل “Serial-AB9874X-2023”)، حيث تلتصق الحروف بالأرقام بشكل مباشر مما يجعل عمليات التقطيع البسيطة المعتمدة على الفواصل عاجزة عن أداء المهمة بدقة. كما تتفاقم الصعوبة عند اختلاف أطوال السلاسل النصية ومواضع القيم الرقمية داخل الحقول عبر السجلات المختلفة ضمن نفس الجدول؛ فقد يقع الرقم في بداية السلسلة في بعض السجلات، وفي منتصفها أو نهايتها في سجلات أخرى، مما يلغي إمكانية الاعتماد على استخراج المقاطع ذات المواقع الثابتة.
بالإضافة إلى ذلك، يُشكل وجود المحارف الخاصة غير المطبوعة، مثل علامات الجدولة (Tabs)، والفواصل السطرية، والمسافات البيضاء المتعددة أو المخفية التي قد تنتج عن عمليات النسخ واللصق من مستندات خارجية، عائقاً كبيراً أمام خوارزميات الاستخراج. كما أن وجود علامات الترقيم المتشابهة في الشكل والمختلفة في الدلالة—مثل استخدام النقطة كفاصلة عشرية أو كنهاية للجملة، واستخدام الشرطة كإشارة سالبة أو كفاصل زمني—يفرض على مهندس البيانات بناء منطق استخراج مرن وشامل يستوعب هذه التباينات دون إسقاط أي جزء من القيمة الرياضية الحقيقية أو إدخال تشوهات في بنية البيانات المستخرجة.
2. الآلية الأساسية: استخدام دالة COMPRESS مع المعدِّلات لاستخراج الأرقام
2.1 البنية التركيبية العامة لدالة COMPRESS وسلوكها الافتراضي
تُعد دالة COMPRESS واحدة من أكثر الدوال تنوعاً وقوة في لغة SAS لمعالجة السلاسل النصية وتنقيتها. في بنيتها التقليدية الأساسية، تستقبل الدالة معاملين: السلسلة النصية المصدر (Source String)، وسلسلة المحارف المراد حذفها (Characters to Remove). في حال تم استدعاء الدالة بتمرير السلسلة المصدر فقط دون تحديد محارف الحذف، فإن سلوكها الافتراضي يتجه حصراً نحو إزالة كافة المسافات البيضاء (Blanks) من السلسلة وإرجاع النص متراصاً. تتجلى القوة الحقيقية لهذه الدالة عند استخدام المعامل الثالث الاختياري، وهو معامل المعدِّلات (Modifiers)، والذي أحدث نقلة نوعية في قدرات المعالجة بدءاً من إصدارات SAS الحديثة، حيث يسمح هذا المعامل بالتحكم في سلوك الدالة وتوجيهها لمعالجة فئات كاملة من الرموز دون الحاجة إلى سردها حرفاً بحرف داخل الشفرة البرمجية.
يوفر نظام المعدِّلات في دالة COMPRESS مرونة استثنائية لمعالجة النصوص بشكل شرطي؛ إذ يمكن للمبرمج توجيه الدالة لاستهداف فئات محددة مثل الحروف الأبجدية، أو الأرقام، أو علامات الترقيم، أو رموز التحكم غير المطبوعة. وتتميز الدالة بقدرتها على استقبال معدلات مفردة أو مدمجة معاً لتنفيذ عمليات تنقية معقدة في سطر برمجي واحد يتسم بالكفاءة العالية وسرعة التنفيذ مقارنة بالحلقات التكرارية اليدوية، مما يجعلها الخيار الأول والأكثر شيوعاً لدى مطوري SAS لاستخراج الأرقام وتنظيف النصوص في خطوط المعالجة اليومية السريعة.

2.2 استخدام المعدِّل ‘A’ لإلغاء الحروف الأبجدية واستبقاء الأرقام
يُستخدم المعدِّل ‘A’ (المشتق من كلمة Alphabetic) لتوجيه دالة COMPRESS نحو إضافة كافة الحروف الأبجدية تلقائياً إلى قائمة المحارف المستهدفة بالحذف، سواء كانت تلك الحروف مكتوبة باللغة الإنجليزية بحالتها الكبيرة (Uppercase) أو الصغيرة (Lowercase). يتم صياغة الاستدعاء البرمجي الأساسي لهذه الحالة بالصيغة: compress(source_string, ”, ‘A’)، حيث يتم ترك المعامل الثاني فارغاً لتوجيه المحرك للاعتماد كلياً على الفئة المعرفة بواسطة المعدِّل. تعمل هذه التعليمة على مسح السلسلة النصية حرفاً بحرف، وإسقاط أي محرف ينتمي إلى الأبجدية اللاتينية (A-Z و a-z)، مع الإبقاء على كافة الرموز الأخرى بما في ذلك الأرقام وعلامات الترقيم والمسافات البيضاء.
ومع ذلك، ينطوي الاعتماد الحصري على المعدِّل ‘A’ على قيد تقني دقيق يجب الانتباه إليه؛ فالدالة في هذا النمط تحذف الحروف الأبجدية فقط، مما يعني أن أي علامات ترقيم، أو فواصل، أو رموز خاصة (مثل الشرطات، والنقاط، والرموز الحسابية) تظل موجودة في السلسلة الناتجة إلى جانب الأرقام. وبالتالي، إذا كانت السلسلة المصدرية تحتوي على رموز غير أبجدية وغير رقمية، فإن الناتج لن يكون رقماً خالصاً، بل سيحتوي على تشوهات قد تمنع تحويله بنجاح إلى متغير رقمي نقي لاحقاً، مما يستدعي استخدام معدلات أكثر صرامة وشمولية لعزل الأرقام الحقيقية بدقة تامة.
2.3 توظيف المعدِّل ‘kd’ لضمان الاحتفاظ بالأرقام حصراً
للتغلب على أوجه القصور المرتبطة بحذف الحروف فقط، توفر لغة SAS معدِّل الحفظ العكسي ‘k’ (المشتق من كلمة Keep)، والذي يقلب المنطق التشغيلي لدالة COMPRESS رأساً على عقب؛ فبدلاً من استخدام الدالة كأداة لحذف محارف محددة، تصبح الدالة أداة لتحديد المحارف المراد الاحتفاظ بها وحذف كل ما سواها. وعند دمج المعدِّل ‘k’ مع المعدِّل ‘d’ (المشتق من كلمة Digits)، تتشكل الصيغة البرمجية القوية: compress(source_string, ”, ‘kd’)، والتي تترجم إلى أمر صريح لمحرك SAS بالاحتفاظ بالأرقام من (0 إلى 9) وحذف أي محرف آخر أياً كانت طبيعته، سواء كان حرفاً أبجدياً، أو مسافة بيضاء، أو رمزاً خاصاً، أو علامة ترقيم.
يمثل استخدام التركيبة ‘kd’ المعيار الذهبي والأكثر أماناً وموثوقية في استخراج الأرقام الصحيحة من السلاسل النصية الملوثة بالشوائب المتعددة. فبالمقارنة الفنية بين استخدام المعدِّل ‘A’ والمعدِّل ‘kd’، نجد أن ‘A’ هو نهج سلبي يعتمد على الحذف الجزئي لقائمة محددة من الرموز، مما يجعله عرضة للفشل إذا احتوت البيانات على رموز غير متوقعة، بينما يمثل ‘kd’ نهجاً إيجابياً يعتمد على المطابقة الحصرية لما هو مطلوب فقط. يضمن هذا النهج الإيجابي تنقية السلسلة تماماً من أي محارف دخيلة وضمان خروج مصفوفة متراصة من الخانات الرقمية الصافية الجاهزة للمراحل التالية من التحليل والتحويل الرياضي.
3. تطبيق عملي: استخراج الأرقام من المعرفات ورموز المقررات الأكاديمية
3.1 إنشاء مجموعة البيانات الأولية باستخدام خطوة البيانات (DATA Step)
لفهم الآلية التطبيقية لاستخراج الأرقام في سيناريو عملي واقعي، سنقوم ببناء مجموعة بيانات تجريبية تحاكي رموز المقررات الدراسية في الجامعات وسجلات التسجيل الأكاديمي، والتي غالباً ما تتألف من اختصارات نصية مدمجة بأرقام المستويات الدراسية والشعب وفصول التسجيل. يتم إنشاء هذا الجدول باستخدام خطوة البيانات DATA Step مع توظيف تعليمة DATALINES (أو CARDS) لإدخال عينات متنوعة تشمل سلاسل نصية مختلفة الأطوال، وبعضها يحتوي على فراغات أو شرطات فاصلة، لتمثيل كافة الحالات الشائعة في بيئات العمل الحقيقية.
يوضح الكود التالي كيفية تعريف مجموعة البيانات المرجعية المسماة ACADEMIC_RECORDS، مع تحديد طول المتغير النصي الأصلي Course_Code بدقة لتجنب اقتطاع أي جزء من النصوص أثناء القراءة:
data ACADEMIC_RECORDS;
length Course_Code $25;
infile datalines truncover;
input Course_Code $;
datalines;
MATH101
ENG_204_ADV
CS-350-LAB
STAT 402 SEC01
PHYS-50
CHEM999FINAL
BIO_NO_DIGIT
12345DIRECT
;
run;
من خلال فحص هذه البنية الأولية عبر نافذة الخصائص أو إجراءات الفحص المبدئي، نتأكد من أن المتغير Course_Code قد تم تعريفه كمتغير نصي بطول 25 بايت، ويحتوي على مزيج من الأرقام، والرموز، والحروف، مما يجعله نموذجاً مثالياً لتطبيق خوارزميات الاستخراج واختبار كفاءتها البرمجية في معالجة التراكيب النصية المتنوعة.
3.2 تطبيق الشفرة البرمجية لاستخراج الأرقام وتفسير المخرجات
بعد إنشاء جدول البيانات الأساسي، نقوم بإنشاء خطوة بيانات جديدة لتطبيق دالة COMPRESS باستخدام المعدِّل ‘kd’ لإنشاء متغير جديد يحمل الأرقام المستخرجة فقط. سنقوم بتسمية المتغير الجديد Course_Number_Char للتأكيد على أن الناتج الحالي لا يزال يمثل سلسلة نصية مكونة من أرقام، ولم يتم تحويله بعد إلى متغير رقمي حسابي بحت.
تتم صياغة خطوة المعالجة على النحو التالي:
data EXTRACTED_NUMBERS;
set ACADEMIC_RECORDS;
length Course_Number_Char $15;
Course_Number_Char = compress(Course_Code, ”, ‘kd’);
run;
proc print data=EXTRACTED_NUMBERS noobs;
run;
عند تنفيذ هذه الشفرة البرمجية واستعراض التقرير المخرج عبر إجراء PROC PRINT، نلاحظ التحول الدقيق في محتويات السجلات؛ فالرمز “MATH101” تحول بدقة إلى “101”، والرمز “ENG_204_ADV” تم تجريده من الحروف والشرطات السفلية ليصبح “204”، بينما تم تجميع الأرقام من “STAT 402 SEC01” لتصبح “40201” نتيجة لحذف كافة المسافات والحروف وتراص الأرقام المتبقية. أما السجل “BIO_NO_DIGIT” الذي يخلو تماماً من الخانات الرقمية، فقد تحول إلى قيمة فارغة تماماً (Empty String)، مما يعكس الأداء المنضبط للدالة في عزل المحتوى الرقمي دون إقحام أي قيم غير حقيقية.
3.3 استخراج النصوص وعزلها باستخدام المعدِّل ‘d’ للمقارنة المنهجية
لتعميق الفهم المنهجي لآلية عمل معدلات دالة COMPRESS، من المفيد تطبيق العملية العكسية المتمثلة في عزل الجزء النصي الوصفي من نفس السلسلة، وإسقاط كافة الأرقام. يتحقق ذلك بسهولة من خلال تطبيق المعدِّل ‘d’ منفرداً دون المعدِّل ‘k’؛ حيث يوجه المعدِّل ‘d’ الدالة لحذف كافة الخانات الرقمية (0-9) مع الإبقاء التلقائي على كافة الحروف والرموز الأخرى، أو دمجه مع معدلات أخرى لتنقية النص من علامات الترقيم أيضاً إذا تطلب الأمر.
يوضح الكود التالي كيفية إنشاء متغيرين متوازيين داخل خطوة البيانات نفسها، أحدهما يعزل الأرقام والآخر يعزل الحروف الأبجدية الصافية:
data DUAL_EXTRACTION;
set ACADEMIC_RECORDS;
length Only_Digits $15 Only_Letters$15;
Only_Digits = compress(Course_Code, ”, ‘kd’);
Only_Letters = compress(Course_Code, ”, ‘ka’);
run;
في هذا المثال، استخدمنا التركيبة ‘ka’ (Keep Alphabetic) لحفظ الحروف فقط وحذف الأرقام والشرطات والمسافات معاً. تظهر مخرجات هذه الخطوة الفصل التام بين المكونين؛ فحقل “CS-350-LAB” يتفكك إلى المتغير الرقمي “350” والمتغير النصي “CSLAB”. تكتسب هذه التقنية المزدوجة أهمية استثنائية في هندسة البيانات عند الرغبة في تفكيك المفاتيح المركبة غير المعيارية إلى مكوناتها الأساسية، وإعادة هيكلة الجداول الوصفية لتسهيل عمليات الربط (Table Joining) مع الجداول المرجعية الأخرى في مستودعات البيانات المركزية.
4. التعامل مع الرموز الخاصة والمسافات البيضاء أثناء استخراج الأرقام
4.1 سلوك دالة COMPRESS تجاه علامات الترقيم والرموز الخاصة
عند تنظيف البيانات المسترجعة من الأنظمة المتعددة، تبرز مشكلة احتواء النصوص على تشكيلة واسعة من علامات الترقيم والرموز الخاصة مثل الشرطات (-)، والشرطات المائلة (/، )، والنقاط (.)، وعلامات التنصيص، والأقواس، والرموز الحسابية. كما أسلفنا، فإن استخدام المعدلات البسيطة مثل المعدِّل ‘A’ يتجاهل هذه الرموز تماماً ويتركها ملتصقة بالأرقام داخل السلسلة المخرجة. فإذا كانت السلسلة الأصلية تحتوي على تاريخ نصي مثل “Date: 2023-10-15″، فإن تطبيق compress(string, ”, ‘A’) سينتج عنه “: 2023-10-15″، وهو نص لا يزال غير صالح للتحويل الرقمي لوجود النقطتين الرأسيتين والشرطات والمسافات.
لذلك، يجب على المبرمج الإلمام بالفئات التصنيفية للرموز داخل محرك SAS. توفر لغة SAS معدلات خاصة لاستهداف هذه الرموز المحددة؛ فالمعدِّل ‘P’ (المشتق من Punctuation) يستهدف كافة علامات الترقيم القياسية، بينما يستهدف المعدِّل ‘C’ (المشتق من Control characters) رموز التحكم المخفية مثل محارف نهاية الأسطر والترميزات غير الرسومية. إن الفهم الدقيق لسلوك كل معدل يتيح للمحلل صياغة استراتيجيات تنقية دقيقة تتناسب مع درجة تلوث البيانات، بدلاً من اللجوء إلى التخمين البرمجي الذي قد يؤدي إلى نتائج غير متوقعة في بيئات الإنتاج.
4.2 دمج المعدِّلات المتعددة لتنقية السلاسل النصية المعقدة
تكمن القوة المتقدمة لدالة COMPRESS في قدرتها على دمج سلاسل متعددة من المعدلات معاً في معامل استدعاء واحد دون حدوث أي تعارض، مما يتيح بناء فلاتر تنقية شديدة التخصيص. يمكن للمبرمج الجمع بين معدل الحفظ ‘k’ ومعدلات تصنيفية متعددة لتحديد مجموعة معقدة من الرموز المسموح ببقائها. على سبيل المثال، إذا أردنا استخراج الأرقام مع الحفاظ على الفواصل والمسافات لفصل المجموعات الرقمية، يمكننا استخدام التركيبة compress(source_string, ‘ ,’, ‘kd’) حيث يحدد المعامل الثاني قائمة إضافية بالمحارف المسموح بالاحتفاظ بها بجانب الأرقام.
يوضح الجدول التالي أبرز المعدِّلات شائعة الاستخدام في دالة COMPRESS وكيفية دمجها لاستخراج وتنقية الأرقام:
| المعدِّل (Modifier) | الوظيفة والوصف التقني | مثال الاستخدام والتطبيق |
|---|---|---|
| d (Digits) | يحدد كافة الأرقام العشرية من (0 إلى 9). | compress(str, ”, ‘d’) لحذف الأرقام. |
| a (Alphabetic) | يحدد كافة الحروف الأبجدية اللاتينية (كبيرة وصغيرة). | compress(str, ”, ‘a’) لحذف الحروف. |
| k (Keep) | يقلب منطق الدالة للاحتفاظ بالمحارف المحددة بدلاً من حذفها. | compress(str, ”, ‘kd’) لحفظ الأرقام فقط. |
| p (Punctuation) | يحدد كافة علامات الترقيم والرموز القياسية. | compress(str, ”, ‘p’) لحذف علامات الترقيم. |
| s (Space) | يحدد كافة المسافات البيضاء وعلامات الجدولة والتحكم الفضائي. | compress(str, ”, ‘s’) لإزالة الفراغات الموسعة. |
| i (Ignore Case) | تجاهل حالة الأحرف عند تحديد محارف حذف مخصصة. | compress(str, ‘abc’, ‘i’) لحذف ABC بأي حالة. |
4.3 معالجة المسافات البينية والنهائية وضبط طول السلسلة الناتجة
عند استخراج الأرقام من السلاسل النصية، قد تترك العمليات مسافات بيضاء بادئة (Leading) أو لاحقة (Trailing) أو فراغات متفرقة في السلسلة الناتجة إذا لم يتم استخدام المعدِّل ‘kd’ بشكل كامل، أو عند الرغبة في الحفاظ على مسافة واحدة فاصلة بين الأرقام المتعددة داخل الحقل الواحد. في مثل هذه الحالات، يجب الاستعانة بالدوال التكميلية المتخصصة في معالجة المسافات داخل SAS لضمان تنظيف السلسلة بالكامل وضبط مساحتها التخزينية في الذاكرة.
تأتي دالة STRIP في مقدمة هذه الأدوات، حيث تقوم بحذف كافة المسافات البادئة واللاحقة معاً بشكل قطعي، بينما تقوم دالة TRIM بحذف المسافات اللاحقة فقط. كما توفر دالة COMPBL وظيفة حيوية تتمثل في تقليص المسافات البيضاء المتعددة المتتالية لتصبح مسافة مفردة واحدة فقط (Compress Blanks). بعد تطبيق هذه الدوال، من الضروري دائماً التحقق من استخدام تعليمة LENGTH لتحديد البعد التخزيني الدقيق للحقل الجديد، حيث يمنع ذلك محرك SAS من حجز الطول التلقائي للمتغير المصدر في المتغير الهدف، وهو ما يضمن ترشيد استخدام الذاكرة المؤقتة ومساحة القرص الصلب أثناء معالجة ملايين السجلات.
5. استخدام التعابير النمطية (Perl Regular Expressions) للاستخراج المتقدم
5.1 مقدمة لدوال PRX في SAS وأهميتها في مطابقة الأنماط
على الرغم من الكفاءة العالية لدالة COMPRESS في تصفية المحارف البسيطة، إلا أنها تفتقر إلى القدرة على فهم السياق التركيبي للبيانات، مثل التمييز بين رقم الهاتف، والرقم البريدي، ورقم الهوية إذا كانت جميعها مدمجة داخل فقرة نصية واحدة. هنا تبرز الأهمية الاستثنائية لدوال التعابير النمطية المتوافقة مع لغة بيرل والمعروفة في SAS بحزمة دوال PRX (Perl Regular Expressions). تعتمد هذه الدوال على محرك قواعد نمطية متطور قادر على البحث عن الأنماط المعقدة، والتحقق من صحة التراكيب النصية، واستبدال الأجزاء المستهدفة أو استخلاصها بدقة فائقة بالاعتماد على قواعد الصياغة المنطقية.
تشتمل حزمة PRX على عدة دوال مركزية، أبرزها دالة PRXPARSE التي تتولى مهمة تجميع النمط التعبيري والتحقق من صحته الرياضية داخل الذاكرة وإرجاع معرف رقمي للنمط (Pattern ID)، ودالة PRXCHANGE التي تنفذ عمليات البحث والاستبدال النمطي، ودالة PRXSUBSTR التي تعزل موضع وطول السلسلة المطابقة للنمط. يتيح استخدام هذه المنظومة لمحللي البيانات بناء استعلامات استخراج شديدة التعقيد تستند إلى شروط سياقية، كأن يتم استخراج الأرقام التي تأتي حصراً بعد كلمة معينة أو الأرقام التي تتكون من عدد محدد من الخانات تفصل بينها رموز معينة.

5.2 بناء أنماط التعابير النمطية لعزل الأرقام المتصلة والمنفصلة
تستخدم التعابير النمطية في SAS رموزاً وصفية خاصة لبناء قواعد الاستخراج. يُستخدم الرمز d للدلالة على أي خانة رقمية من 0 إلى 9، بينما يشير الرمز D (بحرف كبير) إلى أي محرف غير رقمي. وعند إضافة محددات التكرار مثل علامة الجمع (+)، والتي تعني تكرار العنصر لمرة واحدة أو أكثر، يصبح التعبير d+ قادراً على مطابقة أي مجموعة متصلة من الأرقام الرياضية بغض النظر عن طولها داخل النص.
لعزل الأرقام وحذف كل ما سواها باستخدام محرك التعابير النمطية، يمكن توظيف دالة PRXCHANGE باستخدام نمط الاستبدال القياسي s/[^d]// مع وضع المعدِّل العام ‘g’ (Global) لتنفيذ الاستبدال عبر كامل السلسلة النصية. تعني هذه الصياغة استبدال أي محرف ليس رقماً بسلسلة نصية فارغة. يوضح الكود التالي التطبيق العملي لهذه التقنية داخل خطوة البيانات:
data REGEX_EXTRACTION;
length Raw_Text $50 Clean_Num$20;
Raw_Text = “Invoice #INV-98745/Total: 4500USD”;
retain Pattern_ID;
if _N_ = 1 then Pattern_ID = prxparse(‘s/[^d]//’);
Clean_Num = prxchange(Pattern_ID, -1, Raw_Text);
run;
من خلال استخدام تعليمة RETAIN والشرط if _N_ = 1، نضمن تجميع النمط مرة واحدة فقط عند قراءة السجل الأول بدلاً من إعادة تجميعه مع كل سجل، وهو ما يوفر سرعة معالجة عالية تضاهي أداء الدوال التقليدية وتمنح مرونة مطلقة في التعامل مع النصوص المعقدة.
5.3 استخراج أرقام محددة السياق كأرقام الهواتف والرموز البريدية
في العديد من التطبيقات المهنية، لا يكون الهدف هو استخراج كافة الأرقام المتناثرة داخل السلسلة ودمجها معاً، بل استخراج رقم معين يمثل كياناً مستقلاً بذاته مثل رقم الحساب البنكي، أو الرقم الضريبي، أو رقم الهاتف المحمول، مع تجاهل أرقام التواريخ أو الكميات الأخرى الموجودة في نفس النص. تتيح ميزة مجموعات الالتقاط (Capture Groups) في التعابير النمطية عبر الأقواس الهلالية () تحقيق هذا الهدف بدقة متناهية.
على سبيل المثال، إذا كان النص يحتوي على صيغة مثل: “Customer ID: CID-8899, Order: 45 units, Phone: (555) 123-4567″، ونرغب في استخراج رقم الهاتف فقط بصيغته النقية المكونة من 10 أرقام، يمكننا بناء تعبير نمطي يستهدف البنية الهاتفية المحددة واستخلاص الأرقام المعزولة عبر دالة PRXPOSN كما يوضح المثال البرمجي التالي:
data PHONE_EXTRACTION;
length Contact_Info $100 Phone_Only$15;
Contact_Info = “Client notes: Call ASAP at (800) 555-0199 for verification”;
retain Regex_ID;
if _N_ = 1 then Regex_ID = prxparse(‘/(?(d{3}))?[-. ]?(d{3})[-. ]?(d{4})/’);
if prxmatch(Regex_ID, Contact_Info) then do;
call prxposn(Regex_ID, 1, pos1, len1);
call prxposn(Regex_ID, 2, pos2, len2);
call prxposn(Regex_ID, 3, pos3, len3);
Phone_Only = cats(substr(Contact_Info, pos1, len1), substr(Contact_Info, pos2, len2), substr(Contact_Info, pos3, len3));
end;
run;
توضح هذه الشفرة كيفية عزل الأجزاء الرقمية المحددة وتجميعها عبر دالة CATS في متغير نقي “8005550199”، مع تجاوز أي أرقام أخرى لا تتطابق مع الهيكل البنائي المستهدف لرقم الهاتف، وهو ما يعكس القدرات الفائقة لمحرك PRX في هندسة البيانات المعقدة.
6. تحويل السلسلة النصية المستخرجة إلى متغير رقمي حقيقي باستخدام دالة INPUT
6.1 مشكلة بقاء المخرجات كمتغير نصي بعد استخدام دالة COMPRESS
من الأخطاء المفاهيمية الشائعة بين المطورين المبتدئين في بيئة SAS الاعتقاد بأن استخدام دالة COMPRESS لاستخراج الأرقام يحول المتغير تلقائياً إلى متغير رقمي. الحقيقة التقنية الصارمة هي أن دالة COMPRESS هي دالة معالجة نصية، وبالتالي فإن القيمة المرجعة منها هي دائماً وأبداً قيمة نصية (Character Value)، حتى لو أصبحت تحتوي على الخانات الرقمية فقط مثل “98754”. تظل هذه القيمة محكومة بخصائص المتغيرات النصية من حيث المحاذاة لليسار، وحجز الذاكرة بالبايت، وعدم القدرة على الخضوع للعمليات الحسابية المباشرة.
إذا حاول المبرمج استخدام هذا المتغير النصي الناتج في معادلة حسابية مباشرة، مثل: Total = Extracted_Digits * 1.15;، فإن محرك SAS سيقوم بالتحويل الضمني (Implicit Conversion) ويُسجل ملاحظة تحذيرية في سجل النظام (SAS Log) بالصيغة القياسية: NOTE: Character values have been converted to numeric values. قد يبدو هذا التحويل التلقائي مريحاً للوهلة الأولى، ولكنه ينطوي على مخاطر برمجية جسيمة؛ ففي حال واجه المحرك سجلاً يحتوي على قيمة نصية فارغة مشوبة بمسافة غير مرئية أو رمز غير قابل للتحويل، فسيتوقف التحويل التلقائي ويولد قيمة مفقودة (Missing Value) مع رسالة خطأ صريحة Invalid numeric data، مما قد يؤدي إلى تشويه نتائج التحليل دون تنبيه مبكر، ويبرز الحاجة الملحة لإجراء التحويل الصريح عبر دالة INPUT.
6.2 تطبيق دالة INPUT وقواعد التنسيق الإدخالي (Informat)
تمثل دالة INPUT في لغة SAS الأداة القياسية والمعيارية لإجراء التحويل النوعي الصريح (Explicit Type Conversion) من السلاسل النصية إلى المتغيرات الرقمية. تعمل هذه الدالة على قراءة السلسلة النصية وتفسير محتوياتها بالاعتماد على قالب تنسيق إدخالي محدد يُعرف باسم Informat، ثم إرجاع القيمة كمتغير رقمي نقي يخضع لقواعد الحساب العشري بالفاصلة العائمة. البنية العامة للدالة هي: numeric_variable = input(character_source, informat.);.
من الضروري اختيار التنسيق الإدخالي المناسب لطبيعة الأرقام المستخرجة؛ ففي الحالات العامة للأرقام الصحيحة الخالية من الفواصل، يُستخدم التنسيق القياسي BESTw. (مثل BEST12. أو BEST32.) أو التنسيق العددي البسيط w.d (مثل 8.). أما إذا كانت السلسلة النصية المستخرجة تحتوي على فواصل ألفية تم استبقاؤها عمداً، فيجب استخدام التنسيق COMMAw. (مثل COMMA12.) الذي يتولى تلقائياً تجاهل الفواصل وتفسير القيمة الرقمية الإجمالية بدقة متناهية، كما يوضح النموذج التالي:
data CONVERT_TO_NUMERIC;
length String_Data $20;
String_Data = “Amount: 125,400 USD”;
/* استخراج الأرقام مع الفاصلة */
Clean_Char = compress(String_Data, ‘,’, ‘kd’);
/* تحويل صريح للمتغير الرقمي */
Numeric_Amount = input(Clean_Char, comma12.);
run;
تضمن هذه الصياغة الثنائية تنقية البيانات أولاً عبر دالة COMPRESS ثم تحويلها المنضبط عبر دالة INPUT، مما يقضي تماماً على أي تحذيرات في سجل النظام ويضمن توافق المتغير الجديد مع كافة الإجراءات الإحصائية اللاحقة.
6.3 معالجة التنسيقات الكبيرة والأرقام ذات المنازل العشرية
عند التعامل مع الأرقام الطويلة جداً مثل المعرفات الوطنية، وأرقام الحسابات البنكية الدولية (IBAN)، أو المقادير العلمية ذات الدقة العشرية العالية، يجب توخي الحذر الشديد عند تحديد عرض التنسيق الإدخالي (Informat Width) في دالة INPUT. إذا تم تحديد عرض تنسيق أقل من طول السلسلة الرقمية (مثل استخدام input(string, 4.) لقيمة تتكون من 8 أرقام)، فإن SAS سيقتطع الرقم ويقرأ الخانات الأربع الأولى فقط، مما يتسبب في خطأ فادح في دقة البيانات.
كقاعدة عامة في أفضل الممارسات البرمجية، يُفضل دائماً استخدام تنسيقات عريضة ومرنة مثل BEST32. أو COMMA32. لاستيعاب أي طول محتمل للمدخلات دون اقتطاع. وفي حالة الأرقام التي تحتوي على منازل عشرية، مثل استخراج قيم القياسات المخبرية (مثل “Level: 14.75 mmol/L”)، يجب التأكد من أن التنسيق الإدخالي قادر على قراءة الفاصلة العشرية في موضعها الحقيقي دون إزاحة رياضية غير مقصودة، وهو ما سنفصله في المحور المخصص لمعالجة الأرقام الكسرية والعشرية.
7. استخراج الأرقام باستخدام دوال الموقع والتقطيع (SCAN و SUBSTR و FIND)
7.1 استخدام دالة SCAN لتفكيك النصوص المعتمدة على الفواصل والمحددات
في الحالات التي تكون فيها السلاسل النصية مهيكلة جزئياً بالاعتماد على محددات أو فواصل قياسية تفصل بين الكلمات والمقاطع الرقمية (مثل الشرطة، أو الفاصلة المنقوطة، أو علامة السلاش)، تصبح دالة SCAN الخيار الأكثر كفاءة وأناقة برمجية لاستخراج الأرقام. تعتمد دالة SCAN على تقسيم السلسلة النصية إلى مقاطع أو كلمات بناءً على قائمة محددات معينة، ثم استرجاع المقطع المطلوب بناءً على ترتيبه العددي داخل السلسلة، وفق البنية: scan(string, n, ‘delimiters’, ‘modifiers’).
تتميز دالة SCAN في الإصدارات الحديثة من SAS بقدرتها على استقبال معدلات وظيفية تشبه دالة COMPRESS؛ حيث يمكن للمعدِّل ‘d’ في دالة SCAN جعل أي رقم فاصلاً، أو العكس باستخدام محددات ترقيم صريحة. على سبيل المثال، إذا كان لدينا حقل مسجل بالصيغة “PART-XYZ_QTY-500_LOC-01″، ونرغب في استخراج الكمية “500”، يمكننا ببساطة استدعاء المقطع الرابع المحدد بالشرطة السفلية والشرطة العادية، كما يوضح المثال التالي:
data SCAN_EXAMPLE;
length Inventory_Record $30 Quantity_Str$10;
Inventory_Record = “PART-XYZ_QTY-500_LOC-01”;
Quantity_Str = scan(Inventory_Record, 4, ‘-_’);
Quantity_Num = input(Quantity_Str, best8.);
run;
يتيح هذا الأسلوب الوصول المباشر إلى الجزء الرقمي دون الحاجة إلى معالجة كامل السلسلة حرفاً بحرف، وهو ما يوفر حلاً ممتازاً للبيانات الناتجة عن سجلات الأنظمة اللوجستية والمستودعات.
7.2 توظيف دالة SUBSTR عند ثبات موقع وطول القيمة الرقمية
تُعد دالة استقطاع النصوص SUBSTR الأداة ذات الكفاءة الحسابية الأعلى وسرعة التنفيذ القصوى داخل محرك SAS، ولكنها تشترط ثباتاً تاماً في مواضع وأطوال الخانات الرقمية داخل السلسلة عبر كافة سجلات جدول البيانات. تستقبل الدالة ثلاثة معاملات: السلسلة المصدرية، موضع البداية (Start Position)، وطول المقطع المراد استقطاعه (Length)، وفق الصيغة: substr(string, position, length).
تُستخدم هذه الطريقة بكثرة في معالجة السجلات المؤسسية القديمة التي تعتمد على الجداول ذات التنسيق الثابت (Fixed-Width Data)، مثل المعرفات الحكومية حيث تمثل الخانات من 1 إلى 3 رمز المنطقة، والخانات من 4 إلى 9 الرقم التسلسلي للمواطن. يوضح الكود التالي استقطاع المقطع الرقمي بدقة متناهية:
data FIXED_WIDTH_EXTRACTION;
length Govt_ID $12 Regional_Code_Num 8 Serial_Num 8;
Govt_ID = “REG04895421A”;
/* استخراج الأرقام بناء على المواقع الثابتة */
Regional_Code_Num = input(substr(Govt_ID, 4, 2), 2.);
Serial_Num = input(substr(Govt_ID, 6, 6), 6.);
run;
نظراً لعدم قيام دالة SUBSTR بأي عمليات مسح شرطي أو بحث نمطي في الذاكرة، فإن استهلاكها لوحدة المعالجة المركزية (CPU Time) يكاد يكون معدوماً، مما يجعلها الخيار المثالي عند معالجة عشرات الملايين من السجلات المنضبطة معمارياً.
7.3 دمج دوال البحث INDEX و FIND لتحديد مواقع الأرقام ديناميكياً
عندما تكون مواقع الأرقام متغيرة داخل السلسلة النصية ولكنها تتبع مؤشراً دلالياً معيناً (مثل ظهورها دائماً بعد كلمة محددة أو بعد أول رقم في السلسلة)، يتم دمج دوال البحث الموضعي مثل FIND وINDEX مع دالة ANYDIGIT لبناء خوارزميات تقطيع ديناميكية عالية المرونة.
تُرجع دالة ANYDIGIT(string) رقم الموضع لأول محرف رقمي يظهر داخل السلسلة النصية، وتُرجع القيمة (0) إذا كانت السلسلة تخلو من الأرقام تماماً. كما توفر SAS دالة NOTDIGIT(string, start) التي تبحث عن أول محرف غير رقمي بدءاً من موضع معين. من خلال دمج هاتين الدالتين، يمكن للمبرمج حساب موضع بداية ونهاية الكتلة الرقمية ديناميكياً ثم استخراجها عبر SUBSTR دون كتابة تعابير نمطية معقدة، كما في النموذج التالي:
data DYNAMIC_SEARCH;
length Text_Entry $40 Dynamic_Num_Str$10;
Text_Entry = “Batch processing ID: 48950 (Archived)”;
Start_Pos = anydigit(Text_Entry);
if Start_Pos > 0 then do;
End_Pos = notdigit(Text_Entry, Start_Pos);
if End_Pos = 0 then Num_Len = length(Text_Entry) – Start_Pos + 1;
else Num_Len = End_Pos – Start_Pos;
Dynamic_Num_Str = substr(Text_Entry, Start_Pos, Num_Len);
Extracted_Value = input(Dynamic_Num_Str, best12.);
end;
run;
يقدم هذا المنطق الخوارزمي حلاً متقدماً يجمع بين سرعة دوال التقطيع الأصلية وقدرة التكيف الديناميكي مع النصوص المتغيرة في الطول والموضع.
8. معالجة الأرقام العشرية والكسور والإشارات السالبة في السلاسل النصية
8.1 المحافظة على النقطة العشرية أثناء عملية الاستخراج
من أبرز المخاطر البرمجية التي تقع عند استخدام دالة COMPRESS بالمعدِّل ‘kd’ بشكل غير مدروس هو قيام الدالة بحذف النقطة العشرية (Decimal Point) تلقائياً، حيث يعتبرها المحرك علامة ترقيم غير رقمية. فإذا كانت السلسلة الأصلية تحتوي على القياس “Weight: 75.50 kg”، فإن تطبيق compress(string, ”, ‘kd’) سيؤدي إلى إرجاع السلسلة “7550”، مما يضخم القيمة الرياضية بمقدار مائة ضعف ويتسبب في كوارث تحليلية عند إدخال هذه البيانات في الحسابات الإحصائية.
لحل هذه المعضلة بدقة، يجب توجيه دالة COMPRESS صراحة للاحتفاظ برمز النقطة العشرية إلى جانب الأرقام. يتحقق ذلك بتمرير رمز النقطة في المعامل الثاني للدالة مع استبقاء المعدِّل ‘kd’، بالصيغة: compress(source_string, ‘.’, ‘kd’). تخبر هذه الصياغة محرك SAS بالاحتفاظ بكل ما هو رقم عشري بالإضافة إلى محرف النقطة، مما يضمن خروج السلسلة “75.50” سليمة تماماً ومستعدة للتحويل الرياضي الصحيح عبر دالة INPUT.

8.2 استخراج الإشارات الجبرية المرتبطة بالأرقام (الموجبة والسالبة)
في البيانات المالية والمناخية، تكتسب الإشارات الجبرية (+ و -) أهمية جوهرية لتحديد طبيعة القيمة الرياضية سواء كانت أرباحاً أو خسائر، أو درجات حرارة فوق أو تحت الصفر المئوي. وبالمثل، فإن حذف الإشارة السالبة يحول كافة القيم السالبة إلى قيم موجبة مشوهاً التحليل المالي والإحصائي. بالإضافة إلى ذلك، تعتمد بعض الأنظمة المحاسبية القديمة على وضع الأرقام السالبة بين قوسين دائريين مثل “(1500.00)” بدلاً من وضع إشارة الناقص الصريحة.
للتعامل مع الإشارات السالبة الصريحة، نقوم بتوسيع قائمة المحارف المستبقاة لتشمل علامة الناقص: compress(source_string, ‘.-‘, ‘kd’). أما في حالة المحاسبة بالأقواس، فيمكن استخدام دالة التعابير النمطية أو استبدال الأقواس بإشارة سالبة مسبقاً قبل تطبيق دالة INPUT مع التنسيق المحاسبي المخصص NEGPARENw.d أو COMMAw.d، كما يوضح الكود التالي:
data FINANCIAL_CLEANING;
length Ledger_Entry $25 Clean_Str$20 Amount 8;
Ledger_Entry = “Loss: (4,500.75) USD”;
/* الاحتفاظ بالأرقام، النقاط، الفواصل، والأقواس */
Clean_Str = compress(Ledger_Entry, ‘.,()’, ‘kd’);
/* قراءة القيمة المحاسبية باستخدام تنسيق يفهم الأقواس كسالب */
Amount = input(Clean_Str, comma15.2);
run;
يضمن هذا التنسيق تفسير القيمة بين القوسين وتحويلها مباشرة إلى القيمة الرقمية الحقيقية -4500.75 دون فقدان دلالتها المالية السلبية.
8.3 تنظيف الأرقام المقترنة بوحدات القياس والرموز المالية
غالباً ما تأتي الأرقام في قواعد البيانات مقترنة ببادئات العملات العالمية مثل ($، €، £، SAR) أو لواحق وحدات القياس الفيزيائية والنسب المئوية مثل (kg, cm, %, Mbps). تمثل هذه الرموز الملتصقة عائقاً مباشراً أمام إجراء الحسابات إذا لم يتم تجريدها بالكامل مع الحفاظ على القيمة الكسرية بدقة.
في حالة النسب المئوية مثل “Discount: 15.5%”، فإن الاستخراج المباشر يعطي السلسلة “15.5”. ولكن في التحليل الإحصائي، يجب أن تُمثل النسبة ككسر عشري (أي 0.155). يوفر SAS التنسيق الإدخالي PERCENTw. الذي يستطيع قراءة السلسلة النصية المتضمنة لرمز “%” مباشرة وتحويلها إلى كسر عشري، مما يوفر خطوة المعالجة اليدوية. يوضح المثال التالي استخراج المقادير والنسب المالية:
data METRIC_CLEANING;
length Raw_Value $20;
Raw_Value = “Discount rate: 12.5%”;
/* استخراج النسبة مع رمزها */
Clean_Percent_Str = compress(Raw_Value, ‘.%’, ‘kd’);
/* التحويل المباشر إلى قيمة عشرية حقيقية 0.125 */
Decimal_Rate = input(Clean_Percent_Str, percent8.2);
run;
يساعد هذا التوظيف الذكي لقوالب الإدخال المتقدمة في اختصار مراحل المعالجة البرمجية وضمان اتساق المقاييس الرياضية عبر خط أنابيب البيانات.
9. إدارة الحالات الاستثنائية والقيم المفقودة أثناء معالجة النصوص
9.1 التعامل مع السلاسل النصية الخالية من أي أرقام
في مجموعات البيانات الكبيرة والمتنوعة، من الشائع جداً مواجهة سجلات تحتوي على سلاسل نصية تخلو تماماً من أي محتوى رقمي، مثل تسجيل عبارات “Not Applicable”، أو “Pending”، أو حقول فارغة أصلاً. عند تطبيق دالة COMPRESS(string, ”, ‘kd’) على مثل هذه السجلات، فإن القيمة المرجعة تكون سلسلة نصية فارغة تماماً بطول صفري محشوة بفراغات بيضاء.
عند تمرير هذه السلسلة الفارغة إلى دالة INPUT، يتعامل محرك SAS معها بسلاسة من خلال توليد قيمة مفقودة رقمية قياسية متمثلة برمز النقطة (.)، دون إيقاف تنفيذ خطوة البيانات. ومع ذلك، للتحقق من سلامة البيانات وعزل هذه السجلات لأغراض التدقيق المحاسبي والإحصائي، يُفضل استخدام دالة MISSING أو فحص طول السلسلة المستخرجة قبل التحويل، كما في الكود التالي:
data MISSING_HANDLING;
set ACADEMIC_RECORDS;
length Extracted_Str $15;
Extracted_Str = compress(Course_Code, ”, ‘kd’);
if missing(Extracted_Str) then do;
Numeric_Result = .;
Data_Flag = “No Numbers Found”;
end;
else do;
Numeric_Result = input(Extracted_Str, best12.);
Data_Flag = “Valid Numeric Extraction”;
end;
run;
تضمن هذه المعالجة الشرطية توثيق مسار كل سجل داخل الجدول وتمنع حدوث التباس بين الصفر الحقيقي والقيم المفقودة الناتجة عن غياب الأرقام في النص الأصلي.
9.2 معالجة النصوص التي تحتوي على مجموعات رقمية متباعدة
تظهر مشكلة معقدة أخرى عندما تحتوي السلسلة النصية المصدرية على مجموعات رقمية متعددة ومتباعدة تمثل حقائق بيانية منفصلة داخل نفس الحقل، مثل السلسلة: “Patient aged 45 with blood pressure 120 over 80”. إذا قمنا بتطبيق compress(string, ”, ‘kd’) بشكل مباشر، فإن الناتج سيكون “4512080”، وهو رقم مدمج عديم المعنى يشوه البيانات الطبية بالكامل نتيجة دمج العمر وضغط الدم الانقباضي والانبساطي في كتلة واحدة.
تتطلب إدارة هذه الحالة استراتيجية تفكيك مسبقة؛ إما عن طريق استبدال المسافات والمحارف غير الرقمية بفاصل موحد (مثل الفاصلة أو المسافة المفردة) ثم استخدام دالة SCAN لاستخراج كل رقم على حدة، أو بناء تعبير نمطي PRX يلتقط المجموعات الثلاث في متغيرات مستقلة، كما هو موضح في النموذج التالي:
data MULTI_NUMBER_SPLIT;
length Medical_Note $60;
Medical_Note = “Patient aged 45 with blood pressure 120 over 80”;
/* استبدال كل ما هو ليس رقماً بمسافة مفردة */
Spaced_Str = prxchange(‘s/[^d]+/ /’, -1, Medical_Note);
/* تنظيف المسافات المحيطة واستخراج كل رقم بموضعه */
Age_Val = input(scan(Spaced_Str, 1, ‘ ‘), best8.);
Systolic = input(scan(Spaced_Str, 2, ‘ ‘), best8.);
Diastolic= input(scan(Spaced_Str, 3, ‘ ‘), best8.);
run;
يحول هذا الأسلوب النص غير المنظم إلى ثلاثة أعمدة كمية واضحة ومستقلة، مما يحافظ على المعنى الدلالي الدقيق لكل رقم تم رصده في السلسلة النصية الأصلية.
9.3 التحقق من صحة البيانات المخرجة واكتشاف أخطاء التحويل البرمجي
تُعد مرحلة التحقق من الجودة خطوة إلزامية في خطوط أنابيب معالجة البيانات الاحترافية في SAS. يجب على مهندس البيانات مراقبة سجل النظام (SAS Log) بدقة للتأكد من خلوه تماماً من أخطاء التحويل من النوع NOTE: Invalid data for… والتي تشير إلى محاولة دالة INPUT قراءة سلاسل تحتوي على رموز غير متوافقة مع التنسيق الإدخالي المختار.
لتتبع السجلات الشاذة برمجياً وتصحيحها قبل اعتماد الجداول النهائية، يمكن استخدام تعليمة PUT الشرطية لطباعة تفاصيل السجل المعيب في سجل النظام أو توجيهه إلى جدول استثناءات مستقل، بالإضافة إلى استخدام إجراء التكرارات الإحصائية PROC FREQ أو إجراء فحص البيانات PROC UNIVARIATE لاكتشاف القيم المتطرفة (Outliers) التي قد تكون نتجت عن دمج غير مقصود لأرقام متباعدة، كما يوضح الكود التالي:
data VALIDATED_DATA ERROR_LOG(keep=Course_Code Error_Reason);
set ACADEMIC_RECORDS;
length Extracted_Char $15;
Extracted_Char = compress(Course_Code, ”, ‘kd’);
/* التحقق من طول الرقم المستخرج */
if length(Extracted_Char) > 8 then do;
Error_Reason = “Extracted number exceeds expected length”;
output ERROR_LOG;
end;
else do;
Clean_Number = input(Extracted_Char, ?? best8.);
output VALIDATED_DATA;
end;
run;
لاحظ استخدام المعدِّل ?? قبل التنسيق الإدخالي داخل دالة INPUT؛ حيث يعمل هذا المعدِّل المتقدم على قمع رسائل الخطأ التحذيرية في سجل النظام وقمع طباعة السجل المعيب تلقائياً عندما يفشل التحويل، مما يتيح للمبرمج التحكم الكامل في إدارة ومعالجة الاستثناءات برمجياً دون تلويث ملف السجل.
10. تحسين كفاءة المعالجة والأداء الحسابي في مجموعات البيانات الضخمة
10.1 مقارنة الكفاءة الحسابية بين دوال COMPRESS ودوال PRX
عند معالجة مجموعات البيانات الضخمة (Big Data) التي تحتوي على عشرات أو مئات الملايين من السجلات داخل بيئات مثل SAS Grid أو الحوسبة السحابية (SAS Viya)، يصبح استهلاك وقت وحدة المعالجة المركزية (CPU Time) وزمن الاستجابة عاملاً حاسماً في اختيار المنهجية البرمجية لاستخراج الأرقام. تظهر المقارنات المعيارية (Benchmarking) تفوقاً كاسحاً لدالة COMPRESS المدعومة بالمعدلات مقارنة بدوال التعابير النمطية PRX في المهام المباشرة لتصفية المحارف.
يعود هذا التفوق الحسابي إلى أن دالة COMPRESS مكتوبة بلغة C المنخفضة المستوى ومدمجة في صميم نواة محرك SAS، مما يجعل عمليات مسح وتصفية البايتات تتم بسرعة فائقة وبأقل قدر من تعليمات المعالج. في المقابل، يتطلب محرك PRX إنشاء كائنات نمطية وتتبع فروع المطابقة النمطية في الذاكرة، وهو ما يفرض حملاً حسابياً إضافياً. لذلك، كقاعدة ذهبية في تحسين الأداء: إذا كان بالإمكان إنجاز عملية استخراج الأرقام باستخدام دالة COMPRESS ومعدلاتها، فيجب تفضيلها دائماً على دوال PRX لضمان سرعة المعالجة وتقليل استهلاك الموارد الحسابية.
10.2 إدارة الذاكرة وضبط أطوال المتغيرات بدقة باستخدام LENGTH
في بيئة SAS، إذا تم إنشاء متغير نصي جديد دون تحديد طوله مسبقاً عبر تعليمة LENGTH، فإن محرك خطوة البيانات يقوم افتراضياً بتعيين طول المتغير الجديد ليطابق طول المتغير المصدر الأصلي، أو يمنحه طولاً افتراضياً قد يصل إلى 200 بايت. في الجداول الضخمة التي تحتوي على ملايين الصفوف، يتسبب هذا التخصيص العشوائي في إهدار هائل لمساحة الذاكرة العشوائية (RAM) ومساحة التخزين المؤقت على القرص الصلب (SASWORK Library)، مما يبطئ عمليات القراءة والكتابة (I/O Bottlenecks).
لتجنب هذا الهدر، يجب دائماً وضع تعليمة LENGTH في صدارة خطوة البيانات وقبل استدعاء دوال الاستخراج، مع تحديد الطول الأدنى الكافي لاستيعاب أكبر قيمة رقمية متوقعة. يوضح الجدول التالي مقارنة استهلاك الذاكرة لمجموعة بيانات تحتوي على 10 ملايين سجل بناءً على ضبط أطوال المتغيرات:
| استراتيجية التخصيص | طول المتغير المحدد | حجم الملف التقريبي (10M سجل) | كفاءة الإدخال/الإخراج (I/O Performance) |
|---|---|---|---|
| تخصيص افتراضي دون LENGTH | $200 بايت | ~2.0 جيجابايت | بطيء جداً بسبب استهلاك النطاق الترددي للقرص |
| تخصيص غير منضبط لطول المصدر | $50 بايت | ~500 ميجابايت | متوسط الكفاءة |
| تخصيص منضبط ومحسن | $8 بايت | ~80 ميجابايت | أقصى سرعة ممكنة مع توفير 95% من الذاكرة |
10.3 تقنيات المعالجة المجمعة والمعالجة متعددة الخيوط (Multithreading)
لتحقيق أقصى درجات التسريع البرمجي في معالجة السلاسل النصية المعقدة عبر مجموعات البيانات العملاقة، يمكن الاستفادة من بيئة المعالجة المتقدمة SAS DS2 وتقنيات المعالجة متعددة الخيوط (Multithreading). تتيح لغة DS2 تنفيذ خطوات تنظيف النصوص واستخراج الأرقام بالتوازي عبر خيوط معالجة متعددة (Threads) تعمل في وقت واحد عبر أنوية المعالج المتعددة، بدلاً من المعالجة التسلسلية أحادية الخيط في خطوة البيانات التقليدية.
يوضح النموذج التالي هيكل معالجة متعدد الخيوط باستخدام لغة DS2 لتنقية حقول النصوص واستخراج الأرقام على دفعات متوازية:
proc ds2;
thread CleanThread / overwrite=yes;
dcl varchar(30) Course_Code;
dcl double Extracted_Num;
method run();
set ACADEMIC_RECORDS;
/* استخدام دالة الضغط داخل بيئة DS2 */
Extracted_Num = to_double(compress(Course_Code, ”, ‘kd’));
output;
end;
endthread;
run;
data PARALLEL_OUTPUT / overwrite=yes;
dcl thread CleanThread t;
method run();
dcl int thread_count;
set from t threads=4;
output;
end;
enddata;
run;
quit;
تؤدي هذه المعالجة المتوازية إلى تقليص زمن التنفيذ الكلي بنسبة تصل إلى 70% في الخوادم متعددة الأنوية، مما يمثل حلاً مثالياً للمؤسسات المالية وشركات الاتصالات التي تتعامل مع تدفقات بيانات ضخمة ومستمرة.
11. مقارنة شاملة بين مختلف منهجيات استخراج الأرقام في SAS
11.1 مصفوفة المفاضلة الفنية: السرعة والتعقيد والمرونة
يتطلب اتخاذ القرار الهندسي السليم لاختيار الأداة المثلى لاستخراج الأرقام موازنة فنية دقيقة بين ثلاثة معايير أساسية: سرعة التنفيذ الحسابي (Execution Speed)، مرونة التعامل مع تباين النصوص (Flexibility)، ودرجة تعقيد الكود البرمجي وصيانته (Code Maintainability). تتميز لغة SAS بتوفير خيارات متعددة تناسب مختلف السيناريوهات التشغيلية.
تلخص المصفوفة التالية التقييم الفني المقارن بين المنهجيات الأربع الرئيسية المتاحة في SAS:
| المنهجية البرمجية | السرعة الحسابية (Performance) | المرونة والقدرة على التكيف | سهولة الصيانة والتعلم | أفضل حالة استخدام |
|---|---|---|---|---|
| COMPRESS (‘kd’) | فائقة جداً (الأسرع) | متوسطة (عزل عام للأرقام) | سهلة للغاية ومباشرة | استخراج كافة الأرقام وتصفية النصوص البسيطة. |
| SUBSTR / INDEX | فائقة جداً | منخفضة (تتطلب ثبات المواقع) | متوسطة الصعوبة | السجلات المنظمة ذات الأطوال والمواضع الثابتة. |
| SCAN | عالية جداً | متوسطة (تعتمد على الفواصل) | سهلة وواضحة | استخراج مقاطع رقمية تفصلها محددات معينة. |
| PRX (Regular Expressions) | متوسطة (أعلى في استهلاك CPU) | استثنائية (أعلى درجات المرونة) | تتطلب خبرة متقدمة | استخراج أرقام محددة السياق من نصوص فوضوية. |
11.2 سيناريوهات تطبيقية لاختيار الطريقة المثلى
لتوضيح كيفية توظيف هذه المصفوفة في البيئات المهنية، نستعرض ثلاثة سيناريوهات واقعية. في السيناريو الأول: عند معالجة حقول العناوين والرموز البريدية البسيطة حيث تلتصق الحروف بالأرقام مثل “Box1048″، فإن استخدام compress(Address, ”, ‘kd’) يمثل الحل الأسرع والأكثر كفاءة لتجريد النص من الحروف والحصول على الرقم البريدي الصافي دون تعقيدات برمجية.
في السيناريو الثاني: عند استخراج المعرفات الرقمية من الباركود وكودات المنتجات العالمية (UPC/EAN) حيث يكون الرقم دائماً مكوناً من 12 خانة تبدأ من الموضع الرابع للسلسلة، فإن استخدام substr(Barcode, 4, 12) يوفر أقصى سرعة تنفيذ ممكنة في قواعد البيانات الكبيرة. أما في السيناريو الثالث: عند التعامل مع التقارير الطبية والملاحظات السريرية غير المهيكلة (Clinical Notes) التي تحتوي على جرعات دوائية وتواريخ وأرقام هواتف داخل فقرات سردية، فإن اللجوء إلى دوال PRX يصبح خياراً حتمياً لعزل كل رقم بناءً على الكلمات السابقة له وسياقه الدلالي الفريد.
11.3 دراسة حالة واقعية لتحويل بيانات نصية فوضوية إلى جداول تحليلية
لتطبيق المنهجية المتكاملة، نفترض وجود جدول بيانات خام DIRTY_INVENTORY يمثل مخزون مستودع يتضمن نصوصاً فوضوية تجمع بين معرفات القطع، والكميات المقترنة بوحدات قياس، والأسعار المحاطة برموز العملات، وتواريخ المعاملات داخل حقل وصفي واحد غير منسق. سنقوم ببناء خطة تنظيف متكاملة تستخدم أفضل التقنيات المجمعة لتحويل هذه الفوضى النصية إلى جدول تحليلي نقي تماماً.
يوضح الكود التالي خطة التنظيف الشاملة وتطبيقها خطوة بخطوة:
data CLEAN_INVENTORY;
length Raw_Record $80 Clean_ID$10 Unit_Price 8 Stock_Qty 8;
infile datalines truncover;
input Raw_Record $char80.;
/* 1. استخراج معرف القطعة باستخدام SCAN و COMPRESS */
Item_Token = scan(Raw_Record, 1, ‘;’);
Clean_ID = compress(Item_Token, ”, ‘kd’);
/* 2. استخراج السعر مع الحفاظ على الفاصلة العشرية */
Price_Token = scan(Raw_Record, 2, ‘;’);
Price_Char = compress(Price_Token, ‘.’, ‘kd’);
Unit_Price = input(Price_Char, best8.2);
/* 3. استخراج كمية المخزون وتجريدها من وحدات القياس */
Qty_Token = scan(Raw_Record, 3, ‘;’);
Qty_Char = compress(Qty_Token, ”, ‘kd’);
Stock_Qty = input(Qty_Char, best8.);
/* 4. حساب القيمة الإجمالية للمخزون برمجياً */
Total_Value = Unit_Price * Stock_Qty;
drop Item_Token Price_Token Price_Char Qty_Token Qty_Char;
datalines;
ITEM: #A-99482; Price: $14.50 USD; QTY: 150 Units
ITEM: #B-10023; Price: $120.00 USD; QTY: 45 PCS
ITEM: #C-55841; Price: $0.75 USD; QTY: 2500 Pack
;
run;
proc print data=CLEAN_INVENTORY noobs;
format Unit_Price Total_Value dollar12.2 Stock_Qty comma8.;
run;
يوضح هذا المثال التطبيقي كيف أدت الخوارزمية المتسلسلة إلى تحويل السجلات النصية المشوشة إلى جدول بيانات مهيكل، مع إنشاء متغير كمي جديد Total_Value خضع لعملية ضرب حسابية مباشرة، وهو ما يؤكد نجاح عملية الاستخراج والتحويل النوعي الصريح للبيانات.
12. أفضل الممارسات البرمجية وبناء دوال ماكرو (SAS Macros) قابلة لإعادة الاستخدام
12.1 كتابة شفرات برمجية قياسية وقابلة للصيانة والتوثيق
تتطلب كتابة الشفرات البرمجية الاحترافية في بيئة SAS الالتزام الصارم بمعايير التوثيق وتسمية المتغيرات بما يضمن سهولة قراءة الكود وصيانته من قبل فرق العمل المختلفة. عند استخراج الأرقام من السلاسل النصية، يجب تجنب إعادة استخدام نفس اسم المتغير النصي لتخزين القيمة الرقمية الناتجة؛ إذ لا يسمح محرك SAS بتغيير نوع المتغير (Type Mutation) داخل نفس خطوة البيانات، ومحاولة فعل ذلك ستؤدي إلى فشل تنفيذ الكود فوراً.
بدلاً من ذلك، يُنصح باعتماد نمط تسمية معياري واضح يعكس حالة المتغير؛ مثل استخدام البادئة c_ أو اللاحقة _char للمتغيرات النصية المؤقتة، واستخدام n_ أو _num للمخرجات الرقمية النهائية. كما يجب دائماً تضمين تعليقات توضيحية داخل الكود البرمجي توضح سبب اختيار معدلات معينة في دالة COMPRESS (مثل توضيح استبقاء النقطة العشرية لحفظ الكسور)، وهو ما يقلل من زمن استكشاف الأخطاء وإصلاحها (Debugging) ويسهل عمليات تدقيق جودة البرمجيات المؤسسية.
12.2 تطوير ماكرو SAS مرن لاستخراج الأرقام آلياً عبر الجداول المختلفة
لتجنب تكرار كتابة نفس الأسطر البرمجية عبر مشاريع التحليل المتعددة، يُعد بناء وحدات ماكرو مخصصة (SAS Macros) خطوة استراتيجية لأتمتة عمليات استخراج الأرقام وتحويلها. سنقوم بتطوير ماكرو ديناميكي يحمل الاسم %ExtractNumeric يستقبل أربعة معاملات مرنة: اسم جدول البيانات المصدر، اسم العمود النصي المراد تنظيفه، اسم المتغير الرقمي الجديد المستهدف، وخيار يحدد ما إذا كانت الأرقام تحتوي على منازل عشرية أم لا.
يوضح الكود التالي البنية الهيكلية الشاملة لهذا الماكرو المتقدم مع تضمين فحوصات التحقق من صحة المدخلات:
%macro ExtractNumeric(data_in=, data_out=, text_var=, num_var=, has_decimal=NO);
%let has_decimal = %upcase(&has_decimal);
data &data_out;
set &data_in;
length _temp_extracted_char $32;
/* تحديد معدلات الضغط بناء على وجود الفواصل العشرية */
%if &has_decimal = YES %then %do;
_temp_extracted_char = compress(&text_var, ‘.-‘, ‘kd’);
&num_var = input(_temp_extracted_char, ?? best32.);
%end;
%else %do;
_temp_extracted_char = compress(&text_var, ‘-‘, ‘kd’);
&num_var = input(_temp_extracted_char, ?? best32.);
%end;
drop _temp_extracted_char;
run;
%put NOTE: Macro ExtractNumeric executed successfully for table &data_out.;
%mend ExtractNumeric;
يمكن استدعاء هذا الماكرو بسهولة في أي مرحلة من مراحل المعالجة البرمجية بسطر واحد فقط، كما يلي: %ExtractNumeric(data_in=ACADEMIC_RECORDS, data_out=CLEAN_RECORDS, text_var=Course_Code, num_var=Course_ID, has_decimal=NO);، مما يوفر أداة معيارية فائقة المرونة تضمن توحيد معايير المعالجة وجودة المخرجات عبر كامل المؤسسة.
12.3 الخلاصة والتوصيات المستقبلية لإدارة خطوط أنابيب تنظيف البيانات
يمثل استخراج الأرقام من السلاسل النصية في بيئة SAS مهارة محورية تجمع بين المعرفة النظرية بخصائص أنواع البيانات والتمكن العملي من ترسانة الدوال المتنوعة. أظهرت هذه الدراسة التفصيلية أن دالة COMPRESS المزودة بالمعدل ‘kd’ تمثل الحل الأمثل والأسرع لمعظم مشكلات استخراج الأرقام البسيطة، بينما توفر دوال PRX حلاً فائق المرونة للتعامل مع النصوص الفوضوية ذات السياقات المحددة، في حين تظل دالة INPUT الجسر الحتمي لتحويل النصوص المستخرجة إلى متغيرات كمية صالحة للتحليل الرياضي والإحصائي.
كنصيحة ختامية لإدارة خطوط أنابيب تنظيف البيانات في المشاريع الكبرى، يوصى دائماً بدمج خطوات التحقق من صحة البيانات (Data Validation) وعزل السجلات الشاذة بشكل آلي كجزء ثابت في خطوة المعالجة، والحرص على ترشيد استخدام الذاكرة من خلال ضبط أطوال المتغيرات مسبقاً عبر تعليمات LENGTH. ومع التطور المستمر لمنصات التحليل المؤسسي مثل SAS Viya، فإن تبني المعالجة المتوازية عبر وحدات DS2 ووحدات الماكرو المؤتمتة يمثل الضمانة الأكيدة لبناء بنية تحتية لتحليل البيانات تتسم بالقوة، والدقة، وقابلية التوسع لمواكبة متطلبات البيانات الضخمة المستقبلية.
References
- Cody, R. (2018). Cody’s Data Cleaning Techniques Using SAS (3rd ed.). SAS Institute. https://support.sas.com/en/books.html
- Carpenter, A. (2012). Carpenter’s Complete Guide to the SAS Macro Language (3rd ed.). SAS Institute. https://support.sas.com/en/books.html
- SAS Institute Inc. (2023). SAS(R) 9.4 Functions and CALL Routines: Reference. SAS Institute Inc., Cary, NC. https://documentation.sas.com
- SAS Institute Inc. (2023). SAS(R) DS2 Programmer’s Guide. SAS Institute Inc., Cary, NC. https://go.documentation.sas.com
- Jansen, L. (2020). Lex Jansen SAS Papers and Technical Documents Archive. https://www.lexjansen.com
- Delwiche, L. D., & Slaughter, S. J. (2019). The Little SAS Book: A Primer (6th ed.). SAS Institute. https://support.sas.com/en/books.html