كيفية تحويل عدد صحيح إلى سلسلة نصية في PySpark (مع مثال)

دليل أكاديمي شامل يشرح كيفية تحويل الأعمدة من نوع عدد صحيح إلى سلسلة نصية في PySpark باستخدام الدالة cast مع أمثلة عملية وتحليل للأداء.

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

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

تتبوأ هندسة البيانات الضخمة مكانة مركزية في البنية التحتية للمؤسسات الحديثة، حيث تتطلب معالجة تدفقات البيانات الهائلة عبر الأنظمة الموزعة دقة تقنية متناهية في نمذجة البيانات وإدارتها. وتُعد مكتبة PySpark، وهي واجهة بايثون البرمجية لمنظومة Apache Spark، إحدى الركائز الأكثر فاعلية واعتمادية في تنفيذ عمليات الاستخراج والتحويل والتحميل (ETL) وإدارة بحيرات البيانات (Data Lakes). ومع ذلك، فإن الطبيعة الهجينة لمنظومة PySpark، التي تجمع بين مرونة بايثون وحزم بيئة التنفيذ الآلية لآلة جافا الافتراضية (JVM)، تفرض تحديات هيكلية دقيقة تتعلق بإدارة نظام الأنواع (Type System)، وتحويل البيانات بين الأنماط المختلفة، لاسيما التحويل من الأعداد الصحيحة إلى السلاسل النصية.

يمثل تحويل نوع البيانات (Type Casting) من عدد صحيح (Integer) إلى سلسلة نصية (StringType) عملية جوهرية تبدو في ظاهرها يسيرة، إلا أنها تنطوي على تعقيدات معمارية تؤثر على تخصيص الذاكرة، وخطة التنفيذ المنطقية والمادية للمحرك التحسيني Catalyst Optimizer، وآليات ضغط البيانات وتخزينها في الذاكرة عبر محرك Tungsten. تنبع الحاجة إلى هذا التحويل من سياقات تشغيلية متعددة؛ مثل توحيد المفاتيح المركبة، وإعداد المعرفات الرقمية للتوافق مع واجهات برمجة التطبيقات (APIs) المستندة إلى ترميز JSON، ومواءمة مخططات البيانات (Schema Conformance) عند دمج مجموعات بيانات غير متجانسة المصدر، وتفادي المعاملة الحسابية غير المقصودة لبيانات ذات طبيعة تصنيفية كالأرقام البريدية أو المعرفات القومية.

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

1. مقدمة تأصيلية حول تمثيل البيانات ومعالجة الأنواع في بيئة الحوسبة الموزعة PySpark

1.1 مفهوم نظام الأنواع (Type System) في Apache Spark وPySpark

يقوم نظام الأنواع في منظومة Apache Spark على أساس هندسي يهدف إلى تحقيق الصرامة الرياضية والكفاءة الحوسبية في بيئة موزعة غير متجانسة. تأسس محرك Spark في جامعة كاليفورنيا في بيركلي ضمن مختبر AMPLab عام 2009 تحت إشراف ماتي زاهريا (Matei Zaharia)، وجاء ليتجاوز قيود نموذج MapReduce التقليدي عبر إدخال هياكل البيانات الموزعة المرنة (RDDs)، ثم تطور لاحقاً في الإصدار Spark 1.3 عام 2015 بتقديم واجهة أطر البيانات (DataFrames API) التي نقلت النظام من المعالجة غير المقيدة بالأنواع إلى نظام يعتمد اعتماداً كلياً على المخططات الصريحة (Explicit Schemas).

تكمن أهمية التحديد الصريح للأنواع في قدرة محرك الاستعلامات الداخلي Catalyst Optimizer على إنشاء خطط تنفيذ منطقية وفيزيائية محسنة (Optimized Physical Plans). عندما تُعرف الأعمدة بنظام أنواع صارم، لا يحتاج المحرك إلى فحص كل سجل بصورة ديناميكية لتحديد كيفية معالجته؛ بل يعتمد على البيانات الوصفية المرتبطة بالأنواع (Type Metadata) لتقليص مساحات التخزين المؤقت وتوليد شفرات بايتية (Bytecode) مخصصة عبر تجميع الاستعلامات في وقت التشغيل (Whole-Stage Code Generation). يختلف هذا النمط الهيكلي جذرياً عن معالجة البيانات غير المصنفة أو الديناميكية في بايثون المجردة، حيث تفرض الأخيرة تكلفة حوسبية باهظة ناجمة عن فحص الأنواع الديناميكي وتغليف الكائنات (Boxing/Unboxing).

في بيئة PySpark، يعمل نظام الأنواع كجسر يربط بين بيئة بايثون ومحرك Spark المكتوب بلغة Scala والمشغل فوق JVM. يوفر هذا الجسر توافقاً دلالياً بين كائنات بايثون الأصلية وهياكل البيانات الداخلية لـ Spark، مما يتيح التوزيع الأمثل للمهام عبر العقد العاملة (Worker Nodes) دون إهدار موارد الحوسبة في تخمين ماهية القيم المنقولة عبر الشبكة.

1.2 الفروق الجوهرية بين الأعداد الصحيحة (Integer) والسلاسل النصية (StringType)

تختلف الأعداد الصحيحة عن السلاسل النصية اختلافاً جذرياً في التمثيل الثنائي واستهلاك مساحات الذاكرة الداخلية. تُمثل الأعداد الصحيحة، مثل IntegerType (الذي يستهلك 4 بايت / 32 بت) أو LongType (الذي يستهلك 8 بايت / 64 بت)، كقيم أولية ثنائية ذات طول ثابت يمكن معالجتها مباشرة بواسطة المسجلات الحسابية للمعالج المركزي (CPU Registers). يتيح هذا التمثيل إجراء العمليات الحسابية وعمليات المقارنة الثنائية بكفاءة متناهية، وبأقل استهلاك ممكن للذاكرة المخبأة (CPU Cache).

في المقابل، يُمثل StringType تسلسلاً متغير الطول من المحارف المرمزة غالباً بصيغة UTF-8. يتطلب تخزين السلسلة النصية بنية بيانات أكثر تعقيداً تشمل بايتات لتحديد طول السلسلة، ومؤشرات الذاكرة (Pointers)، ومصفوفات البايت الفعلية، مما يزيد من الحجم الحسابي للبيانات داخل الذاكرة مقارنة بالأرقام. يترتب على هذا الفارق البنيوي تحول في نوعية العمليات المسموح بها؛ فالأعداد الصحيحة تخضع لقوانين الحساب والعمليات الرياضية مثل الجمع والطرح والتجميع التراكمي، بينما تخضع السلاسل النصية للعمليات المعجمية، ومطابقة الأنماط النصية (Regex)، والتحليل اللغوي.

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

1.3 متطلبات تحويل الأنماط (Type Casting) ودوافعها التقنية والتحليلية

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

دافع محوري آخر يتمثل في تحقيق مطابقة مخططات البيانات (Schema Conformance). عند استقبال بيانات من مصادر غير متجانسة—مثل ملفات CSV المهملة ومستودعات تخزين JSON وقواعد بيانات NoSQL—قد يُقرأ حقل معين (كرقم الهاتف أو الرمز البريدي) في بعض المصادر كعدد صحيح، بينما يظهر في مصادر أخرى كسلسلة نصية نتيجة وجود أصفار بادئة. لدمج هذه التدفقات عبر عمليات الاتحاد (Union Operations)، يجب مواءمة نوع البيانات ليصبح نصياً، مما يضمن الحفاظ على المظهر الشكلي ومنع حدوث استثناءات توافق المخطط (Schema Mismatch Exceptions).

كذلك تفرض خطوط التغذية لخوارزميات التعلم الآلي ومعالجة اللغات الطبيعية (NLP) هذا التحويل؛ حيث تتطلب بعض النماذج التعامل مع المتغيرات الفئوية (Categorical Variables) ككيانات نصية لتمريرها إلى محولات التشفير الأحادي (One-Hot Encoders) أو مفهرسات السلاسل (StringIndexers)، مما يجعل التحويل من عدد صحيح إلى نص خطوة تسبق مرحلة استخلاص الخصائص (Feature Engineering).

2. الإطار النظري لبنية أطر البيانات (DataFrames) في PySpark ومخططات البيانات

2.1 دور مخطط البيانات (StructType و StructField) في تعريف الحقول

يرتكز إطار البيانات في PySpark على مخطط هيكلي يحدد أسماء الحقول وأنواعها وقابليتها لاحتواء قيم خالية. يُعرف هذا المخطط برمجياً عبر كائن StructType، الذي يمثل تسلسلاً هرمياً يتكون من مجموعة كائنات من فئة StructField. يحتوي كل StructField على ثلاثة محددات رئيسية: اسم الحقل (سلسلة نصية)، ونوع البيانات المطبق (مشتق من الفئة الأم DataType مثل IntegerType() أو StringType())، وقيمة منطقية (Boolean) تحدد ما إذا كان الحقل يقبل القيم المعدومة (Nullable).

يوفر محرك Spark آلية استنتاج تلقائي للأنواع (Schema Inference) عند قراءة ملفات البيانات مثل JSON أو CSV. ورغم فائدة هذا الاستنتاج في المراحل الاستكشافية، إلا أنه ينطوي على قيود تشغيلية واضحة؛ إذ يتطلب مسحاً إضافياً للبيانات لتخمين النوع الأدق، وقد يفسر الأرقام التعريفية ذات الأصفار البادئة كأرقام صحيحة، مما يؤدي إلى فقدان الأصفار (مثل تحويل “0123” إلى 123). لتفادي هذه التشوهات في بيئات الإنتاج، يُعد التحديد اليدوي الصريح للمخطط ممارسة قياسية لا غنى عنها لضمان الاستقرار المنهجي وحماية البيانات من التلف أثناء الاستيعاب الأولي.

2.2 تأثير التغيير الهيكلي على أداء العمليات واستغلال الذاكرة

تخضع معالجة البيانات في PySpark لمبدأ الحوسبة الكسولة (Lazy Evaluation)، حيث لا تُنفذ التحويلات البرمجية فور كتابتها في النص المصدري، بل تسجل ضمن خطة تنفيذ منطقية (Logical Execution Plan) تُمثل عبر شجرة توجيهية غير دائرية (DAG). عند إجراء عملية تحويل لنوع العمود، يُسجل Catalyst Optimizer عملية التحويل كعقدة جديدة في شجرة العمليات التعبيرية، دون تعديل البيانات الفعلية حتى يُستدعى إجراء تنفيذي (Action) مثل collect() أو count().

على صعيد استهلاك الذاكرة، يؤدي التحويل من عدد صحيح إلى نص إلى زيادة البصمة الكربونية للبيانات ومعدل استهلاك الذاكرة العشوائية داخل العقد العاملة. يعود ذلك إلى سلوك محرك Tungsten، وهو المكون المسؤول عن إدارة الذاكرة وتوليد الأكواد في Spark. يدير محرك Tungsten الذاكرة خارج الكومة (Off-Heap Memory) بتخزين البيانات في مصفوفات بايتية مدمجة تحاكي بنية لغة C وتتجنب جمع المهملات (Garbage Collection Overhead) التابع لـ JVM. الأعداد الصحيحة تُخزن كقيم ثابتة العرض تشغل مساحة متوقعة بدقة، بينما تفرض السلاسل النصية تخزيناً متغير الطول يتطلب مؤشرات إضافية، مما يقلل من كفاءة ضغط الذاكرة المؤقتة ويزيد من حجم البيانات المنقولة عبر المعالج.

2.3 فحص نوع البيانات الحالي باستخدام سمة dtypes وطريقة printSchema

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

من الناحية التحليلية البصرية، توفر الدالة df.printSchema() عرضاً شجرياً واضحاً يوضح البنية الهرمية للمخطط في الطرفية، مبيناً أسماء الحقول ونوع البيانات الحالي وما إذا كان الحقل يقبل القيمة null. يتيح هذا الفحص التمييز بدقة بين تفرعات الأعداد الصحيحة، مثل ByteType (1 بايت)، وShortType (2 بايت)، وIntegerType (4 بايت)، وLongType (8 بايت)، ومقارنتها بنوع الهدف StringType، وهو أمر جوهري لاختيار آلية التحويل الأنسب وضمان التوافق المنطقي للعمليات اللاحقة.

3. البناء البرمجي الأساسي لتحويل الأعداد الصحيحة إلى سلاسل نصية

3.1 استيراد الفئات الأساسية من مكتبة pyspark.sql.types

تبدأ المعالجة البرمجية الدقيقة للأنواع في PySpark باستدعاء الكائنات البنيوية من حزمة pyspark.sql.types. تتضمن هذه الحزمة جميع الفئات الممثلة لنظام الأنواع داخل محرك SQL المدمج. لاستخدام التحويل القائم على الكائنات الصريحة، يتعين استيراد الكائن StringType الذي يرث من الفئة الأساسية AtomicType، والتي ترث بدورها من DataType.

تتم عملية الاستيراد باتباع التوجيه المعياري الآتي:

from pyspark.sql.types import StringType

يوصى هندسياً بتجنب الاستيراد الشامل عبر النجمة (مثل from pyspark.sql.types import *) في المشاريع البرمجية الكبيرة، لتفادي تضارب أسماء الكائنات مع مكتبات بايثون القياسية أو وحدات الطرف الثالث، وللحفاظ على وضوح التبعيات البرمجية داخل بيئات الاختبار والتكامل المستمر (CI/CD).

3.2 آلية عمل الدالة withColumn لإضافة أو تعديل الأعمدة

تعتمد أطر بيانات PySpark بصورة مطلقة على مبدأ عدم القابلية للتغيير (Immutability). بموجب هذا المفهوم المعماري، لا يمكن تعديل إطار بيانات قائم “في مكانه” (In-place)؛ بل تُنتج أي عملية معالجة إطار بيانات جديداً تماماً يشير إلى خطة تنفيذية محدثة. تؤدي دالة withColumn دوراً مركزياً في هذه الآلية، حيث تستقبل معاملين أساسيين: اسم العمود المراد إنشاؤه أو تعديله كمعامل أول، والتعبير العمودي (Column Expression) المحسوب كمعامل ثانٍ.

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

3.3 استخدام دالة التحويل الصريح cast مع StringType

تُعد الدالة cast التابعة لفئة Column في PySpark الوسيلة المعيارية لتحويل نوع البيانات من نسق إلى آخر. تقبل هذه الدالة إما كائناً صريحاً مشتقاً من DataType (مثل StringType())، أو مؤشراً نصياً مكافئاً. الصياغة القياسية للتنفيذ البرمجي تتخذ الشكل التالي:

df_transformed = df.withColumn('column_name', df['column_name'].cast(StringType()))

عند تنفيذ هذا السطر، لا تقوم الدالة بتحويل البيانات بصورة لحظية، بل تبني تعبيراً تحويلياً (Cast Expression) داخل شجرة التعبيرات الخاصة بـ Catalyst. يتحقق المحرك أثناء مرحلة التحليل الدلالي (Semantic Analysis) من إمكانية تطبيق التحويل المطلوب بين النوع المصدر والنوع الوجهة وفق قواعد التوافق المضمنة. وتمثل دالة cast استدعاءً أصيلاً يتم تنفيذه مباشرة داخل JVM بلغة منخفضة المستوى، ما يجعلها تتفوق في سرعتها وكفاءتها على أي محاولة لتطبيق دوال التحويل الخارجية التابعة للغة بايثون.

4. تطبيق عملي مفصل: إنشاء بيئة الاختبار وإعداد إطار البيانات المبدئي

4.1 تهيئة جلسة SparkSession وضبط إعدادات التشغيل

تمثل SparkSession نقطة الدخول الشاملة والتنفيذية لجميع وظائف Apache Spark منذ الإصدار 2.0، حيث وحدت سياقات العمل القديمة مثل SparkContext وSQLContext في واجهة موحدة. تُنشأ الجلسة بالاعتماد على نمط التصميم المنشئ (Builder Pattern)، الذي يتيح تعيين معلمات التهيئة بدقة لضمان استقرار العمليات في بيئات التطوير والاختبار المحلي.

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

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("ConvertIntToStringGuide").master("local[*]").getOrCreate()

يشير التكوين master("local[*]") إلى تشغيل Spark محلياً عبر استخدام جميع الأنوية المنطقية المتاحة في المعالج المركزي لجهاز الاختبار، مما يحاكي بيئة الحوسبة المتوازية. بمجرد استدعاء getOrCreate()، يتم التحقق من وجود جلسة نشطة متوافقة وإعادتها، أو تهيئة جلسة جديدة كلياً وإطلاق سياق JVM التابع لها في الخلفية.

4.2 بناء بيانات تجريبية (بيانات أداء لاعبي كرة السلة)

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

raw_data = [("Lakers", 112), ("Warriors", 104), ("Celtics", 98), ("Bulls", 125), ("Spurs", 89)]

يتم بعد ذلك تحديد أسماء الأعمدة المقابلة في قائمة مستقلة تمهيداً لدمجها مع البيانات:

column_names = ["team", "points"]

يوفر هذا التوزيع تنوعاً عددياً متسقاً، حيث يمثل العمود team معرفاً نصياً اسمياً، بينما يمثل العمود points قيماً كمية عددية صحيحة تخضع للتحويل النصي لاحقاً.

4.3 إنشاء إطار البيانات والتحقق من الأنواع المبدئية

تُدمج البيانات الخام مع أسماء الأعمدة لتشكيل إطار البيانات عبر استدعاء دالة الإنشاء الرسمية التابعة للجلسة:

df_players = spark.createDataFrame(data=raw_data, schema=column_names)

للتأكد البصري من إتمام عملية الاستيعاب وسلامة البنية الجدولية، تُستدعى دالة العرض:

df_players.show()

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

df_players.printSchema()

تظهر المخرجات أن محرك Spark قد استنتج نوع العمود points كـ LongType أو IntegerType (بحسب إعدادات النظام ومعمارية نظام التشغيل)، مؤكداً أن العمود يقع ضمن التصنيف العددي ويستعد لعملية التحويل البرمجي الصريح.

5. تنفيذ عملية التحويل خطوة بخطوة وفحص النتائج

5.1 تطبيق كود التحويل عبر cast(StringType()) وإنشاء العمود الجديد

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

from pyspark.sql.types import StringType

df_with_new_column = df_players.withColumn("points_str", df_players["points"].cast(StringType()))

عند تنفيذ هذه التعليمة، يولد محرك Catalyst شجرة منطقية تحتوي على تعبير التحويل cast(points as string). ونظراً لمبدأ الحوسبة الكسولة، لا تُنسخ البيانات فعلياً في هذه اللحظة، بل يؤجل التنفيذ الفيزيائي المباشر إلى حين طلب استعراض البيانات أو حفظها في وحدة التخزين.

5.2 استبدال العمود الأصلي بدلاً من إضافة عمود إضافي

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

df_players_updated = df_players.withColumn("points", df_players["points"].cast(StringType()))

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

5.3 تأكيد التحويل بنجاح عبر عرض المحتوى وفحص مصفوفة dtypes

للتأكد القاطع من نجاح التحويل البرمجي وسلامة المخرجات، نتحقق من البيانات عبر مستويين؛ الأول وصفي بنيوي، والآخر قيمي بصري. نفحص مصفوفة الأنواع من خلال السمة البرمجية:

print(df_players_updated.dtypes)

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

df_players_updated.show()

يُظهر الفحص البصري أن الأرقام لا تزال تحتفظ بمظهرها الأصلي (مثل “112” و”104″) دون تشويه أو تحويل إلى قيم فارغة، مما يؤكد سلامة عملية التحويل ومحافظتها على دقة البيانات الأساسية.

6. المقارنة بين الطرق البديلة لتحويل الأنماط في PySpark

6.1 التحويل النصي المباشر باستخدام الصيغة الحرفية cast(‘string’)

توفر مكتبة PySpark مرونة بنيوية تسمح للمطورين بالاستغناء عن استيراد كائنات الأنواع الرسمية، وذلك بتمرير المؤشرات الحرفية (String Literals) مباشرة إلى دالة cast. يمكن كتابة التحويل بالصيغة المبسطة التالية:

df_simple = df.withColumn("points", df["points"].cast("string"))

تتميز هذه الطريقة باختصار الكود البرمجي وتقليل عدد أسطر الاستيراد في الملفات، وتؤدي وظيفياً نفس المهمة التي يؤديها استدعاء cast(StringType()) تماماً؛ إذ يقوم مترجم التعبيرات الداخلي لـ Catalyst بمطابقة الكلمة النصية "string" وتحويلها داخلياً إلى مثيل من StringType.

ومع ذلك، تكمن خطورة هذه الطريقة في افتقارها للأمان البرمجي في وقت كتابة الكود (Compile-time Type Safety)؛ فإذا أخطأ المطور إملائياً وكتب cast("strng")، فلن تكتشف بيئات التطوير المتكاملة (IDEs) أو أدوات الفحص الساكن (Linters) هذا الخطأ مسبقاً، بل سيتوقف التنفيذ فجأة في وقت التشغيل مطلقة استثناء AnalysisException نتيجة عدم التعرف على نوع البيانات المطلوب.

6.2 استخدام تعبيرات SQL المباشرة عبر دالة expr ودالة selectExpr

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

df_sql = df.selectExpr("team", "CAST(points AS STRING) AS points")

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

6.3 تطبيق دوال التنسيق المتقدمة مثل format_string لمعالجة السلاسل

في كثير من التطبيقات العملية، لا يقتصر الهدف على مجرد تغيير النوع التقني من رقم إلى نص، بل يتطلب الأمر تعديل الهيئة البصرية للنص الناتج. تبرز هنا دالة format_string المستوحاة من دالة printf في لغة C، والتي تتيح للمهندس تطبيق تنسيقات محددة، مثل إضافة أصفار بادئة (Zero Padding) للأرقام أو توحيد أطوال السلاسل:

from pyspark.sql.functions import format_string

df_formatted = df.withColumn("points_padded", format_string("%05d", df["points"]))

في هذا المثال، لا يتحول الرقم 112 إلى السلسلة “112” فحسب، بل يُعاد تشكيله ليصبح “00112”. تُمثل هذه العملية فارقاً دقيقاً وجوهرياً بين “التحويل الصرف للنوع” (Type Casting) الذي يحافظ على المظهر الرقمي المجرد للبيانات، وبين “التنسيق النصي” (String Formatting) الذي يعيد بناء السلسلة وفق معايير تنسيق محددة، وهو أمر بالغ الأهمية عند توليد رموز الفواتير، أو الرموز البريدية، أو معرفات الحسابات البنكية.

7. التعامل مع القيم المفقودة (Nulls) والحالات الاستثنائية أثناء التحويل

7.1 سلوك دالة cast عند مواجهة قيم خالية (Null Values)

يتميز محرك Apache Spark بتصميم صارم وآمن في التعامل مع القيم الخالية والغياب الرياضي للبيانات (Null Safety). عندما تُطبق دالة cast على عمود يحتوي على قيم خالية (تُمثل كـ null في بيئة Spark أو None في بايثون)، فإن المحرك لا يطلق أي استثناء تشغيلي (Exception)، بل يمرر القيمة الخالية كما هي ليظل الحقل المقابل null في العمود النصي الجديد.

من المهم جداً الانتباه إلى الفرق الدلالي الحاسم بين القيمة المنطقية المعدومة null والسلسلة النصية الحرفية "null" أو "None"؛ فالأولى تدل على غياب القيمة وتخضع لمنطق المعالجة الثلاثي (Three-Valued Logic) في استعلامات SQL، بينما تمثل الثانية سلسلة نصية ذات طول يبلغ 4 محارف لها دلالة حقيقية قد تفسد نتائج التحليلات اللاحقة. إذا تطلب منطق العمل استبدال القيم الخالية بسلاسل نصية افتراضية، يجب تطبيق دالة fillna() أو استدعاء دالة coalesce() قبل أو بعد التحويل لضمان المعالجة المتسقة للحقول الفارغة.

7.2 معالجة الأرقام الكبيرة والأنواع المتفرعة (BigInt و SmallInt)

تتضمن منظومة Spark تصنيفات متعددة للأعداد الصحيحة تتفاوت في مداها الحسابي واستهلاكها للذاكرة، مثل ByteType (-128 إلى 127)، وShortType (-32768 إلى 32767)، وIntegerType (-2^31 إلى 2^31-1)، وLongType (-2^63 إلى 2^63-1). عند تحويل أي من هذه الأنواع إلى StringType، يضمن المحرك عدم فقدان الدقة الرقمية نهائياً؛ حيث يُحول كل رقم صحيح إلى تمثيله النصي الدقيق بصيغة الأساس 10 مهما بلغت ضخامته، مع الاحتفاظ الصارم بعلامات الإشارة الرياضية السالبة.

يجب التمييز هنا بين تحويل الأعداد الصحيحة الصرفة وتحويل الأعداد العشرية ذات الفاصلة العائمة (Float/Double)؛ فالأخيرة قد تواجه مشكلات متعلقة بالتقريب الثنائي والتمثيل العلمي (Scientific Notation مثل 1E10) عند تحويلها إلى نصوص، في حين تتميز الأعداد الصحيحة بثبات تمثيلها المعجمي، مما يجعل تحويلها آمناً تماماً من مخاطر التشويه العددي أو التناقص في دقة المراتب الرياضية.

7.3 استراتيجيات التحقق والتنقية للبيانات الملوثة أو غير المتسقة

في بيئات البيانات المفتوحة وغير الخاضعة لحوكمة صارمة، قد تحتوي مجموعات البيانات على صفوف شاذة أو قيم متطرفة تفرض معالجة شرطية مسبقة قبل التحويل النصي. تُبنى استراتيجيات التنقية والتحقق البرمجي بالاعتماد على التعبيرات الشرطية الممثلة بالدالتين when وotherwise التابعتين لحزمة pyspark.sql.functions:

from pyspark.sql.functions import col, when

df_clean = df.withColumn("points_validated", when(col("points") < 0, "INVALID").otherwise(col("points").cast("string")))

تسمح هذه المنهجية بعزل القيم غير المنطقية (كالنقاط السالبة في المثال) واستبدالها بوسوم نصية واضحة تدل على الخطأ، أو تسجيلها في جداول عزل مستقلة (Dead-Letter Queues) دون التسبب في تعطيل أو إيقاف تدفق معالجة الدفعات الكبيرة (Batch Jobs)، وهو ما يعزز مرونة ومتانة خطوط نقل ومعالجة البيانات في بيئات الإنتاج الفعلية.

8. الأثر الأدائي والاعتبارات المعمارية لتحويل البيانات الضخمة

8.1 كفاءة استهلاك الذاكرة وحجم التخزين بين الأنواع الرقمية والنصية

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

يمتد هذا التأثير إلى ضغط البيانات على الأقراص؛ فعند حفظ البيانات بصيغ التخزين العمودية الحديثة مثل Apache Parquet، تحقق الأعمدة الرقمية معدلات ضغط فائقة بالاعتماد على خوارزميات التشفير الثنائي المتقدمة مثل تشفير دلتا (Delta Encoding) وتشفير طول التشغيل (Run-Length Encoding – RLE). في المقابل، يؤدي تحويل الأعمدة إلى نصوص إلى انخفاض ملحوظ في كفاءة هذه الخوارزميات، مما يزيد من الحجم الإجمالي للملفات على وسائط التخزين، ويرفع بدوره أوقات عمليات جمع المهملات (Garbage Collection) في JVM نتيجة تكاثر مراجع الكائنات النصية في الذاكرة.

8.2 تأثير التحويل على عمليات التجزئة (Partitioning) والخلط (Shuffling)

تعتمد العمليات التجميعية والربط في PySpark (مثل groupBy وjoin) على عمليات إعادة توزيع البيانات بين العقد العاملة عبر الشبكة، وهي العملية المعروفة هندسياً بالخلط الموزع (Data Shuffling). تستخدم Spark دوال تجزئة رياضية (Hash Functions)، مثل MurmurHash3، لتحديد العقدة العاملة المسؤولة عن معالجة كل مفتاح معين بناءً على نوعه وقيمته الثنائية.

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

8.3 تفادي تكلفة التحويل المتكرر داخل خطوط المعالجة الممتدة

نظراً لطبيعة الحوسبة الكسولة في Apache Spark، فإن تكرار استدعاء إطار البيانات المحول في عدة إجراءات تنفيذية متتالية (Actions) يؤدي إلى إعادة حساب شجرة التحويل في كل مرة من البداية، ما لم يُخزن إطار البيانات وسيطياً في الذاكرة. إذا كانت مجموعة البيانات ضخمة وتتطلب مسحاً مكثفاً للسجلات، فإن هذا التكرار يستنزف الموارد الحوسبية دون مبرر.

للتغلب على هذا التبديد الحوسبي، يُنصح بتطبيق استراتيجيات التخزين المؤقت المدروسة باستخدام دالتي cache() أو persist() بمستوى التخزين المناسب (مثل StorageLevel.MEMORY_AND_DISK) مباشرة بعد إجراء التحويلات الهيكلية المكلفة:

df_cached = df.withColumn("points_str", df["points"].cast("string")).cache()

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

9. أفضل الممارسات البرمجية وتصميم خطوط أنابيب البيانات (Data Pipelines)

9.1 التوثيق الدقيق لمخططات البيانات في بيئات الإنتاج

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

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

9.2 كتابة اختبارات الوحدة (Unit Testing) للتحقق من سلامة الأنواع

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

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

9.3 تكامل عمليات التحويل مع صيغ التخزين المتقدمة مثل Parquet و Delta Lake

عند حفظ أطر البيانات الناتجة في وسائط التخزين المتطورة مثل صيغة Parquet أو طبقات بحيرات البيانات الحديثة مثل Delta Lake، يجب مراعاة توافق الأنواع المحولة مع قدرات هذه التقنيات. تدعم صيغة Delta Lake ميزات متقدمة مثل التحقق الصارم من المخطط (Schema Enforcement) وتطور المخطط التدريجي (Schema Evolution).

إذا كُتب إطار بيانات يحتوي على عمود تم تحويله حديثاً من عدد صحيح إلى نص فوق جدول دلتا قائم مسبقاً بنوعه الرقمي القديم، فإن المحرك سيعترض فوراً ويطلق استثناءً أمنياً لمنع تلف البيانات، ما لم يُفعل خيار الدمج التلقائي للمخطط عبر إعداد mergeSchema = true. يفرض هذا التكامل المعماري على مهندسي البيانات دراسة متأنية لتداعيات تغيير أنواع البيانات على طبقات القراءة والاستهلاك النهائية، كأنظمة ذكاء الأعمال (BI Tools) ومحركات الاستعلامات التفاعلية الموزعة مثل Trino و Amazon Athena.

10. الأخطاء الشائعة وحلولها التقنية في بيئة العمل الحقيقية

10.1 خطأ استدعاء الدالة على أعمدة غير متوافقة (AnalysisException)

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

df["points"] = str(df["points"])

لا تؤدي هذه المحاولة إلى تحويل البيانات المخزنة داخل الصفوف إطلاقاً، بل تستدعي طريقة __str__ التابعة للغة بايثون على كائن العمود نفسه، مما يحوله إلى تمثيل نصي داخلي مشوه مثل "Column<'points'>"، وينتج عن ذلك فشل فوري في تسجيل الاستعلام وصدور استثناء تحليلي عنيف من نوع AnalysisException أو Py4JError نتيجة تمرير مدخلات غير مدعومة إلى واجهة JVM التحتية.

الحل التقني الصحيح يتمثل دائماً في استخدام التعبيرات العمودية المعتمدة لمحرك Spark عبر دالة cast أو الدوال المدمجة في pyspark.sql.functions، لضمان ترجمة العملية إلى تعبير يفهمه محرك Catalyst الداخلي ويستطيع تطبيقه بالتوازي عبر آلاف المعالجات الفرعية في العقد الموزعة.

10.2 التباس المفاهيم بين التنسيق (Formatting) وتغيير النوع (Casting)

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

على سبيل المثال، تطبيق دالة cast("string") على الأرقام البريدية التي تبدأ بأصفار وكانت قد قُرئت خطأ كأعداد صحيحة لن يعيد الأصفار المفقودة أبداً؛ فالرقم 0123 المخزن كـ 123 سيتحول نصياً إلى “123” فقط. يكمن الحل الصحيح في استخدام دوال التنسيق المخصصة مثل lpad() أو format_string() لإعادة بناء الطول المعياري للسلسلة بإضافة الأصفار على يسار الرقم، مما يؤكد ضرورة الفصل المنهجي بين متطلبات طبقة التخزين التقنية ومتطلبات طبقة العرض الوظيفية.

10.3 إرشادات استكشاف الأخطاء وإصلاحها (Troubleshooting) أثناء التحويل

عند مواجهة اختناقات في الأداء أو انهيارات غير مفسرة لخطوط المعالجة عقب تنفيذ عمليات التحويل، تمثل واجهة المستخدم الرسومية لمحرّك سبارك (Spark UI) الأداة الأكثر موثوقية لتشخيص الخلل. من خلال فحص علامة التبويب “SQL/Dataframe”، يستطيع المهندس استعراض خطة التنفيذ المادية (Physical Plan) والتأكد من عدم وجود عمليات فك تسلسل غير ضرورية ناتجة عن استخدام دوال غير أصلية.

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

@udf(returnType=StringType())
def to_str(x): return str(x)

يتسبب هذا النمط في كارثة أدائية حقيقية؛ حيث يعطل تماماً تحسينات محرك Tungsten، ويجبر النظام على نقل البيانات تسلسلياً ذهاباً وإياباً بين آلة جافا الافتراضية (JVM) ومفسر بايثون عبر بروتوكول Py4J ومقابس الشبكة المحلية، مما يضاعف استهلاك الذاكرة ويبطئ زمن المعالجة بمقدار عشرات المرات مقارنة باستخدام الدالة الأصلية cast(). يتطلب استكشاف الأخطاء الناجح عزل الأعمدة المعطوبة فوراً، والاعتماد المطلق على الدوال المبنية داخلياً (Built-in Spark Expressions) لضمان تحقيق أعلى كفاءة حوسبية ممكنة.

الخلاصة

يمثل تحويل الأعداد الصحيحة إلى سلاسل نصية في بيئة PySpark عملية حيوية تتجاوز في أبعادها الهندسية مجرد استدعاء دالة برمجية بسيطة. كما تبين عبر التحليل الشامل في هذا المقال، يرتبط هذا التحويل ارتباطاً وثيقاً بنظام الأنواع الصارم لمحرّك Apache Spark، وتأثيراته المعمارية الممتدة على محرك التحسين Catalyst ومحرك إدارة الذاكرة Tungsten.

يوفر التحويل الصريح عبر الدالة المعيارية Column.cast(StringType()) أو المؤشر النصي Column.cast("string")، فضلاً عن تعبيرات SQL بواسطة selectExpr، كفاءة تنفيذية متفوقة بفضل بقاء العمليات داخل بيئة JVM وتجنب أعباء فك التسلسل الباهظة بين جافا وبايثون. ومع ذلك، يفرض هذا التحويل زيادة حتمية في استهلاك الذاكرة العشوائية وتراجعاً في كفاءة ضغط البيانات العمودية في ملفات Parquet، فضلاً عن تأثيره المباشر على خوارزميات التجزئة أثناء عمليات الخلط الموزع للبيانات.

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

المراجع

  • Armbrust, M., Xin, R. S., Lian, C., Huai, Y., Liu, D., Bradley, J. K., Meng, X., Kaftan, T., Franklin, M. J., Ghodsi, A., & Zaharia, M. (2015). Spark SQL: Relational data processing in Spark. In Proceedings of the 2015 ACM SIGMOD International Conference on Management of Data (pp. 1383–1394). Association for Computing Machinery. https://doi.org/10.1145/2723372.2742797
  • Chambers, B., & Zaharia, M. (2018). Spark: The definitive guide: Big data processing made simple (1st ed.). O’Reilly Media.
  • Damji, J. S., Wenig, B., Das, T., & Lee, D. (2020). Learning Spark: Lightning-fast data analytics (2nd ed.). O’Reilly Media.
  • Karau, H., & Warren, R. (2017). High performance Spark: Best practices for scaling and optimizing Apache Spark (1st ed.). O’Reilly Media.
  • Zaharia, M., Chowdhury, M., Franklin, M. J., Shenker, S., & Stoica, I. (2010). Spark: Cluster computing with working sets. In Proceedings of the 2nd USENIX Conference on Hot Topics in Cloud Computing (HotCloud’10) (pp. 1–7). USENIX Association.
★

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

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

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

looti, M. (2026, أكتوبر 24). كيفية تحويل عدد صحيح إلى سلسلة نصية في PySpark (مع مثال). عرب سايكلوجي. https://arabpsychology.com/statistics/convert-integer-to-string-pyspark-example/
looti, Mohammed. “كيفية تحويل عدد صحيح إلى سلسلة نصية في PySpark (مع مثال).” عرب سايكلوجي, 24 أكتوبر 2026, https://arabpsychology.com/statistics/convert-integer-to-string-pyspark-example/.
looti, Mohammed. “كيفية تحويل عدد صحيح إلى سلسلة نصية في PySpark (مع مثال).” عرب سايكلوجي. أكتوبر 24, 2026. https://arabpsychology.com/statistics/convert-integer-to-string-pyspark-example/.