الشكل والبيانات النظيفة

مكتمل

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

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

اقرأ البيانات من جدول بحيرة

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

SELECT * FROM raw_sales

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

إزالة الصفوف المكررة

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

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

-- Remove exact duplicate rows
SELECT DISTINCT * FROM raw_sales

-- Or deduplicate by a business key (keeps one row per order_id)
SELECT * FROM (
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY order_date) AS rn
    FROM raw_sales
) WHERE rn = 1

معالجة القيم الفارغة

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

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

-- Replace nulls with default values
SELECT
    order_id,
    customer_id,
    amount,
    COALESCE(region, 'Unknown') AS region,
    COALESCE(discount, 0) AS discount
FROM raw_sales

-- Or drop rows where a required column is null
SELECT * FROM raw_sales
WHERE customer_id IS NOT NULL

بعد استبدال الصفوف الصفرية، تظهر الصفوف التي كانت تظهر مناطق فارغة سابقا "غير معروف"، وتستخدم حسابات الخصم الصفر بدلا من انتشار الصفر.

تصفِية الصفوف

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

SELECT * FROM raw_sales
WHERE YEAR(order_date) = 2024
    AND amount > 0

في PySpark، لف كل شرط بين قوسين واستخدم & ل AND وOR | . هذا يتجنب مشاكل أسبقية المشغل التي قد تؤدي إلى نتائج خاطئة.

اختيار وإعادة تسمية الأعمدة

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

SELECT
    order_id,
    customer_id,
    product_id,
    quantity,
    unit_price,
    order_date,
    region
FROM raw_sales

إضافة الأعمدة المحسوبة

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

SELECT *,
    quantity * unit_price AS line_total,
    YEAR(order_date) AS order_year,
    MONTH(order_date) AS order_month
FROM clean_sales

بعد هذه الخطوة، يتضمن كل صف أجزاء تاريخ محسوبة line_total ومستخرجة مسبقا. الصف الذي يحتوي على الرقم 5 و unit_price 29.99 يظهر الآن قيمة line_total 149.95.

إنشاء الأعمدة الشرطية

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

SELECT *,
    CASE
        WHEN line_total > 500 THEN 'High'
        WHEN line_total > 100 THEN 'Medium'
        ELSE 'Low'
    END AS value_tier
FROM clean_sales

الطلب الذي يبلغ line_total 149.95 يصنف الآن ك "متوسط"، بينما الطلب لعام 199.99 لجهاز بريميوم واحد يندرج في نفس الفئة. تعكس هذه العتبات تعريفات عملك وتظل متسقة في كل استخدام لاحق.

تحويل أنواع البيانات

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

SELECT
    CAST(amount AS DECIMAL(10,2)) AS amount,
    CAST(order_date AS DATE) AS order_date,
    CAST(quantity AS INT) AS quantity
FROM raw_sales

ملاحظة

تدعم Spark SQL و PySpark نفس أنواع البيانات الأساسية. يمكنك خلط اللغتين في نفس الدفتر باستخدام %%sql أمر السحر. اختر أي صيغة تبدو أكثر طبيعية لكل مهمة.

مجموعة البيانات النظيفة

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

قبل بعد
11 صفا مع نسخ مكررة 10 صفوف فريدة
القيم الصفرية في المنطقة والخصم مليء ب "مجهول" و 0
جميع الأعمدة الأصلية الأعمدة المطلوبة فقط، وتسمى بانتظام
لا توجد قيم مشتقة line_total، order_year، order_month، value_tier أضيف
أنواع البيانات الخام من المصدر الأنواع الصريحة للعشرية، والتواريخ، والأعداد الصحيحة

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

يمكنك الآن تشكيل جداول فردية بصيغ نظيفة ومتسقة. في الوحدة التالية، تتعلم دمج البيانات من جداول متعددة وحساب النتائج المجمعة.