3
Pandas: أقوى مكتبة لمعالجة البيانات في Python
📊 الدرس الثالث: Pandas لمعالجة البيانات
🎯 أهداف الدرس
- فهم ما هو Pandas ولماذا هو أساسي لعلم البيانات
- إتقان التعامل مع Series وDataFrame
- قراءة البيانات من ملفات CSV وExcel وJSON
- تنظيف البيانات والتعامل مع القيم المفقودة
- الفهرسة والتقطيع المتقدم للبيانات
- التحليل الإحصائي والتجميع
- دمج وربط مجموعات البيانات المختلفة
- إنشاء تقارير تحليلية شاملة
📋 المتطلبات السابقة
- إكمال الدرسين السابقين: Python الأساسي وNumPy
- فهم NumPy: المصفوفات والعمليات الأساسية
- مفاهيم البيانات: الجداول والصفوف والأعمدة
- Pandas مثبت: pip install pandas
🤔 ما هو Pandas ولماذا هو مهم؟
Pandas (Python Data Analysis Library) هو المكتبة الأساسية لمعالجة وتحليل البيانات في Python. إنه يوفر هياكل بيانات قوية ومرنة للتعامل مع البيانات المنظمة.
Pandas يجعل تحليل البيانات سهلاً ومرئياً
📊 حقائق مذهلة عن Pandas:
- الشعبية: يستخدمه 98% من علماء البيانات
- السرعة: مبني على NumPy للحصول على أداء عالي
- المرونة: يدعم أكثر من 20 تنسيق ملف
- القوة: يتعامل مع ملايين الصفوف بسهولة
- التكامل: يعمل مع جميع مكتبات التصور والتعلم الآلي
🏗️ هياكل البيانات الأساسية
Pandas يوفر هيكلين أساسيين للبيانات:
📋 Series
مصفوفة أحادية البعد مع فهارس مسماة. مثل عمود واحد في جدول Excel.
import pandas as pd
# إنشاء Series
grades = pd.Series([85, 92, 78, 96, 88])
print(grades)
📊 DataFrame
جدول ثنائي البعد مع صفوف وأعمدة مسماة. مثل جدول Excel كامل.
# إنشاء DataFrame
data = {
'الاسم': ['أحمد', 'فاطمة', 'محمد'],
'العمر': [25, 30, 35],
'الراتب': [5000, 6000, 7000]
}
df = pd.DataFrame(data)
print(df)
📥 قراءة البيانات من الملفات
Pandas يدعم قراءة البيانات من تنسيقات متعددة:
Pandas يدعم قراءة البيانات من تنسيقات متعددة
قراءة ملفات CSV
import pandas as pd
# قراءة ملف CSV
df = pd.read_csv('employees.csv')
print(f"شكل البيانات: {df.shape}") # (عدد الصفوف, عدد الأعمدة)
print(f"أول 5 صفوف:
{df.head()}")
# قراءة مع خيارات متقدمة
df_advanced = pd.read_csv(
'data.csv',
encoding='utf-8', # ترميز النص
sep=';', # فاصل الأعمدة
index_col=0, # العمود الأول كفهرس
parse_dates=['التاريخ'], # تحويل التواريخ
na_values=['N/A', 'NULL'] # القيم المفقودة
)
# معلومات عن البيانات
print(f"
معلومات البيانات:")
print(df.info())
print(f"
الإحصائيات الأساسية:")
print(df.describe())
قراءة ملفات Excel
# قراءة ملف Excel
df_excel = pd.read_excel('sales_data.xlsx')
# قراءة ورقة عمل محددة
df_sheet = pd.read_excel('data.xlsx', sheet_name='المبيعات')
# قراءة عدة أوراق عمل
all_sheets = pd.read_excel('data.xlsx', sheet_name=None)
print(f"أوراق العمل المتاحة: {list(all_sheets.keys())}")
# قراءة مع تحديد النطاق
df_range = pd.read_excel(
'data.xlsx',
sheet_name='البيانات',
usecols='A:E', # الأعمدة من A إلى E
skiprows=2, # تجاهل أول صفين
nrows=100 # قراءة 100 صف فقط
)
قراءة تنسيقات أخرى
# قراءة ملف JSON
df_json = pd.read_json('data.json')
# قراءة من قاعدة بيانات SQL
import sqlite3
conn = sqlite3.connect('database.db')
df_sql = pd.read_sql_query('SELECT * FROM employees', conn)
# قراءة من الويب مباشرة
df_web = pd.read_csv('https://example.com/data.csv')
# قراءة ملف HTML (الجداول)
df_html = pd.read_html('https://example.com/table.html')[0]
# قراءة ملف Parquet (للبيانات الكبيرة)
df_parquet = pd.read_parquet('big_data.parquet')
🔍 استكشاف البيانات الأساسي
بعد قراءة البيانات، نحتاج لفهمها واستكشافها:
إنشاء بيانات تجريبية للتدريب
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
# إنشاء بيانات موظفين وهمية
np.random.seed(42)
n_employees = 1000
# إنشاء البيانات
employees_data = {
'الرقم_الوظيفي': range(1001, 1001 + n_employees),
'الاسم': [f'موظف_{i}' for i in range(1, n_employees + 1)],
'القسم': np.random.choice(['المبيعات', 'التسويق', 'التطوير', 'الموارد البشرية', 'المالية'], n_employees),
'العمر': np.random.randint(22, 65, n_employees),
'الراتب': np.random.normal(8000, 2000, n_employees).round(2),
'سنوات_الخبرة': np.random.randint(0, 20, n_employees),
'تاريخ_التوظيف': [datetime.now() - timedelta(days=np.random.randint(30, 3650)) for _ in range(n_employees)],
'الحالة': np.random.choice(['نشط', 'إجازة', 'متدرب'], n_employees, p=[0.8, 0.15, 0.05])
}
# إضافة بعض القيم المفقودة لمحاكاة البيانات الحقيقية
missing_indices = np.random.choice(n_employees, 50, replace=False)
for idx in missing_indices:
employees_data['الراتب'][idx] = np.nan
df = pd.DataFrame(employees_data)
print(f"تم إنشاء بيانات {len(df)} موظف")
print(f"شكل البيانات: {df.shape}")
الاستكشاف الأساسي للبيانات
# نظرة سريعة على البيانات
print("أول 5 صفوف:")
print(df.head())
print("
آخر 5 صفوف:")
print(df.tail())
print("
عينة عشوائية من 5 صفوف:")
print(df.sample(5))
# معلومات عامة عن البيانات
print("
معلومات البيانات:")
print(df.info())
# أسماء الأعمدة
print(f"
أسماء الأعمدة: {list(df.columns)}")
# أنواع البيانات
print("
أنواع البيانات:")
print(df.dtypes)
# حجم البيانات
print(f"
حجم البيانات: {df.shape}")
print(f"عدد الصفوف: {len(df)}")
print(f"عدد الأعمدة: {len(df.columns)}")
# الذاكرة المستخدمة
print(f"
استخدام الذاكرة: {df.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
الإحصائيات الوصفية
# الإحصائيات الأساسية للأعمدة الرقمية
print("الإحصائيات الأساسية:")
print(df.describe())
# إحصائيات شاملة (تشمل النصوص)
print("
إحصائيات شاملة:")
print(df.describe(include='all'))
# إحصائيات مخصصة
print("
إحصائيات مخصصة:")
numeric_cols = df.select_dtypes(include=[np.number]).columns
for col in numeric_cols:
print(f"
{col}:")
print(f" المتوسط: {df[col].mean():.2f}")
print(f" الوسيط: {df[col].median():.2f}")
print(f" الانحراف المعياري: {df[col].std():.2f}")
print(f" أقل قيمة: {df[col].min():.2f}")
print(f" أكبر قيمة: {df[col].max():.2f}")
print(f" المدى: {df[col].max() - df[col].min():.2f}")
# القيم الفريدة في الأعمدة النصية
categorical_cols = df.select_dtypes(include=['object']).columns
for col in categorical_cols:
if col != 'الاسم': # تجاهل عمود الأسماء
print(f"
القيم الفريدة في {col}:")
print(df[col].value_counts())
معالجة البيانات باستخدام Pandas
🎯 الفهرسة والتقطيع
الوصول للبيانات في Pandas أكثر قوة ومرونة من NumPy:
الوصول للأعمدة
# الوصول لعمود واحد (يعيد Series)
ages = df['العمر']
print(f"نوع البيانات: {type(ages)}")
print(f"أول 5 قيم: {ages.head()}")
# الوصول لعدة أعمدة (يعيد DataFrame)
subset = df[['الاسم', 'العمر', 'الراتب']]
print(f"
شكل البيانات الفرعية: {subset.shape}")
# الوصول باستخدام النقطة (للأعمدة بدون مسافات)
# df.العمر # يعمل فقط إذا لم يكن هناك مسافات في اسم العمود
# إنشاء أعمدة جديدة
df['الراتب_السنوي'] = df['الراتب'] * 12
df['فئة_العمر'] = pd.cut(df['العمر'],
bins=[0, 30, 45, 65],
labels=['شاب', 'متوسط', 'كبير'])
print(f"
أول 5 صفوف مع الأعمدة الجديدة:")
print(df[['الاسم', 'العمر', 'فئة_العمر', 'الراتب', 'الراتب_السنوي']].head())
الوصول للصفوف
# الوصول بالفهرس الرقمي
first_employee = df.iloc[0] # أول موظف
print(f"أول موظف:
{first_employee}")
# الوصول لعدة صفوف
first_five = df.iloc[0:5] # أول 5 موظفين
print(f"
أول 5 موظفين:
{first_five[['الاسم', 'القسم', 'الراتب']]}")
# الوصول بالفهرس المسمى (إذا كان متاحاً)
df_indexed = df.set_index('الرقم_الوظيفي')
employee_1001 = df_indexed.loc[1001]
print(f"
الموظف رقم 1001:
{employee_1001}")
# الوصول العشوائي
random_employees = df.sample(3)
print(f"
3 موظفين عشوائيين:
{random_employees[['الاسم', 'القسم', 'الراتب']]}")
# الوصول للصفوف الأخيرة
last_employees = df.tail(3)
print(f"
آخر 3 موظفين:
{last_employees[['الاسم', 'القسم', 'الراتب']]}")
الفلترة والشروط المنطقية
# فلترة بسيطة
high_salary = df[df['الراتب'] > 10000]
print(f"عدد الموظفين براتب أكثر من 10000: {len(high_salary)}")
# فلترة متعددة الشروط
young_developers = df[
(df['العمر'] < 30) &
(df['القسم'] == 'التطوير') &
(df['الراتب'] > 7000)
]
print(f"
المطورين الشباب براتب عالي: {len(young_developers)}")
print(young_developers[['الاسم', 'العمر', 'القسم', 'الراتب']].head())
# فلترة بالقوائم
target_departments = ['المبيعات', 'التسويق']
sales_marketing = df[df['القسم'].isin(target_departments)]
print(f"
موظفي المبيعات والتسويق: {len(sales_marketing)}")
# فلترة النصوص
names_with_ahmed = df[df['الاسم'].str.contains('أحمد', na=False)]
print(f"
الموظفين الذين يحتوي اسمهم على 'أحمد': {len(names_with_ahmed)}")
# فلترة التواريخ
recent_hires = df[df['تاريخ_التوظيف'] > '2023-01-01']
print(f"
الموظفين المعينين حديثاً: {len(recent_hires)}")
# فلترة القيم المفقودة
employees_with_salary = df[df['الراتب'].notna()]
employees_without_salary = df[df['الراتب'].isna()]
print(f"
موظفين بدون راتب محدد: {len(employees_without_salary)}")
🧹 تنظيف البيانات
البيانات الحقيقية نادراً ما تكون نظيفة. تعلم كيفية تنظيفها:
التعامل مع القيم المفقودة
# فحص القيم المفقودة
print("القيم المفقودة في كل عمود:")
missing_data = df.isnull().sum()
print(missing_data[missing_data > 0])
# نسبة القيم المفقودة
print("
نسبة القيم المفقودة:")
missing_percentage = (df.isnull().sum() / len(df)) * 100
print(missing_percentage[missing_percentage > 0])
# طرق التعامل مع القيم المفقودة
# 1. حذف الصفوف التي تحتوي على قيم مفقودة
df_dropped_rows = df.dropna()
print(f"
بعد حذف الصفوف: {df_dropped_rows.shape}")
# 2. حذف الأعمدة التي تحتوي على قيم مفقودة
df_dropped_cols = df.dropna(axis=1)
print(f"بعد حذف الأعمدة: {df_dropped_cols.shape}")
# 3. ملء القيم المفقودة بقيم افتراضية
df_filled = df.copy()
# ملء بالمتوسط للأعمدة الرقمية
df_filled['الراتب'].fillna(df_filled['الراتب'].mean(), inplace=True)
# ملء بالقيمة الأكثر تكراراً للأعمدة النصية
df_filled['القسم'].fillna(df_filled['القسم'].mode()[0], inplace=True)
# ملء بقيمة ثابتة
df_filled['الحالة'].fillna('غير محدد', inplace=True)
print(f"
بعد ملء القيم المفقودة:")
print(df_filled.isnull().sum())
# 4. الاستيفاء (Interpolation) للبيانات الرقمية
df_interpolated = df.copy()
df_interpolated['الراتب'] = df_interpolated['الراتب'].interpolate()
# 5. الملء الأمامي والخلفي
df_forward_fill = df.fillna(method='ffill') # ملء بالقيمة السابقة
df_backward_fill = df.fillna(method='bfill') # ملء بالقيمة التالية
إزالة التكرارات
# إضافة بعض الصفوف المكررة للتجربة
duplicate_rows = df.sample(10).copy()
df_with_duplicates = pd.concat([df, duplicate_rows], ignore_index=True)
print(f"البيانات الأصلية: {len(df)} صف")
print(f"مع التكرارات: {len(df_with_duplicates)} صف")
# فحص التكرارات
duplicates = df_with_duplicates.duplicated()
print(f"عدد الصفوف المكررة: {duplicates.sum()}")
# إزالة التكرارات
df_no_duplicates = df_with_duplicates.drop_duplicates()
print(f"بعد إزالة التكرارات: {len(df_no_duplicates)} صف")
# إزالة التكرارات بناءً على أعمدة محددة
df_unique_names = df_with_duplicates.drop_duplicates(subset=['الاسم'])
print(f"أسماء فريدة: {len(df_unique_names)} صف")
# الاحتفاظ بآخر تكرار بدلاً من الأول
df_keep_last = df_with_duplicates.drop_duplicates(keep='last')
print(f"الاحتفاظ بآخر تكرار: {len(df_keep_last)} صف")
تنظيف النصوص
# إضافة بعض البيانات النصية غير المنظمة للتجربة
messy_names = [
' أحمد محمد ',
'فاطمة_الزهراء',
'محمد-علي',
'SARA AHMED',
'نور الدين'
]
df_messy = pd.DataFrame({'الاسم_غير_منظم': messy_names})
# تنظيف النصوص
df_clean = df_messy.copy()
# إزالة المسافات الزائدة
df_clean['الاسم_منظم'] = df_clean['الاسم_غير_منظم'].str.strip()
# استبدال الرموز
df_clean['الاسم_منظم'] = df_clean['الاسم_منظم'].str.replace('_', ' ')
df_clean['الاسم_منظم'] = df_clean['الاسم_منظم'].str.replace('-', ' ')
# تحويل إلى أحرف صغيرة
df_clean['الاسم_صغير'] = df_clean['الاسم_منظم'].str.lower()
# تحويل إلى أحرف كبيرة
df_clean['الاسم_كبير'] = df_clean['الاسم_منظم'].str.upper()
# تحويل الحرف الأول إلى كبير
df_clean['الاسم_مناسب'] = df_clean['الاسم_منظم'].str.title()
print("تنظيف النصوص:")
print(df_clean)
# تطبيق على بياناتنا الأساسية
df['الاسم_منظم'] = df['الاسم'].str.strip().str.title()
df['القسم_منظم'] = df['القسم'].str.strip().str.title()
# فحص الأقسام الفريدة
print(f"
الأقسام بعد التنظيف:")
print(df['القسم_منظم'].value_counts())
📊 التحليل والتجميع
Pandas يوفر أدوات قوية للتحليل الإحصائي والتجميع:
التجميع الأساسي (GroupBy)
# التجميع حسب القسم
dept_analysis = df.groupby('القسم').agg({
'الراتب': ['mean', 'median', 'std', 'min', 'max', 'count'],
'العمر': ['mean', 'min', 'max'],
'سنوات_الخبرة': ['mean', 'max']
}).round(2)
print("تحليل الأقسام:")
print(dept_analysis)
# تحليل أكثر تفصيلاً
print("
تحليل مفصل للأقسام:")
for dept in df['القسم'].unique():
dept_data = df[df['القسم'] == dept]
print(f"
{dept}:")
print(f" عدد الموظفين: {len(dept_data)}")
print(f" متوسط الراتب: {dept_data['الراتب'].mean():.2f}")
print(f" متوسط العمر: {dept_data['العمر'].mean():.1f}")
print(f" متوسط سنوات الخبرة: {dept_data['سنوات_الخبرة'].mean():.1f}")
# التجميع المتعدد
age_dept_analysis = df.groupby(['فئة_العمر', 'القسم'])['الراتب'].agg([
'count', 'mean', 'std'
]).round(2)
print("
تحليل حسب العمر والقسم:")
print(age_dept_analysis)
# إحصائيات مخصصة
def salary_range(series):
return series.max() - series.min()
custom_stats = df.groupby('القسم')['الراتب'].agg([
'mean',
'median',
salary_range,
lambda x: x.quantile(0.75) - x.quantile(0.25) # المدى الربعي
]).round(2)
custom_stats.columns = ['المتوسط', 'الوسيط', 'المدى', 'المدى_الربعي']
print("
إحصائيات مخصصة:")
print(custom_stats)
الجداول المحورية (Pivot Tables)
# جدول محوري بسيط
pivot_basic = df.pivot_table(
values='الراتب',
index='القسم',
aggfunc='mean'
).round(2)
print("متوسط الراتب حسب القسم:")
print(pivot_basic)
# جدول محوري متقدم
pivot_advanced = df.pivot_table(
values=['الراتب', 'العمر'],
index='القسم',
columns='فئة_العمر',
aggfunc={
'الراتب': 'mean',
'العمر': 'count'
},
fill_value=0,
margins=True # إضافة إجماليات
).round(2)
print("
جدول محوري متقدم:")
print(pivot_advanced)
# جدول تكرارات
crosstab = pd.crosstab(
df['القسم'],
df['فئة_العمر'],
margins=True,
normalize='index' # نسب مئوية
).round(3)
print("
جدول التكرارات (نسب مئوية):")
print(crosstab)
# تحليل الرواتب حسب سنوات الخبرة
experience_bins = pd.cut(df['سنوات_الخبرة'],
bins=[0, 2, 5, 10, 20],
labels=['مبتدئ', 'متوسط', 'خبير', 'خبير جداً'])
salary_by_experience = df.groupby(experience_bins)['الراتب'].agg([
'count', 'mean', 'median', 'std'
]).round(2)
print("
تحليل الرواتب حسب الخبرة:")
print(salary_by_experience)
تحليل البيانات المتقدم باستخدام Pandas
🔗 دمج البيانات
في الواقع العملي، نحتاج غالباً لدمج بيانات من مصادر متعددة:
إنشاء بيانات إضافية للدمج
# إنشاء جدول تقييمات الأداء
performance_data = {
'الرقم_الوظيفي': np.random.choice(df['الرقم_الوظيفي'], 800),
'تقييم_الأداء': np.random.choice(['ممتاز', 'جيد جداً', 'جيد', 'مقبول'], 800),
'النقاط': np.random.randint(60, 100, 800),
'تاريخ_التقييم': [datetime.now() - timedelta(days=np.random.randint(1, 365)) for _ in range(800)]
}
df_performance = pd.DataFrame(performance_data)
print(f"بيانات التقييم: {df_performance.shape}")
print(df_performance.head())
# إنشاء جدول معلومات الأقسام
departments_info = {
'القسم': ['المبيعات', 'التسويق', 'التطوير', 'الموارد البشرية', 'المالية'],
'المدير': ['أحمد محمد', 'فاطمة علي', 'محمد حسن', 'نور الدين', 'سارة أحمد'],
'الميزانية': [500000, 300000, 800000, 200000, 400000],
'عدد_الموظفين_المستهدف': [200, 150, 300, 100, 120]
}
df_departments = pd.DataFrame(departments_info)
print(f"
معلومات الأقسام:")
print(df_departments)
أنواع الدمج المختلفة
# 1. Inner Join - الصفوف الموجودة في كلا الجدولين
inner_join = df.merge(df_performance, on='الرقم_الوظيفي', how='inner')
print(f"Inner Join: {inner_join.shape}")
print(f"الموظفين الذين لديهم تقييم: {len(inner_join)}")
# 2. Left Join - جميع الصفوف من الجدول الأيسر
left_join = df.merge(df_performance, on='الرقم_الوظيفي', how='left')
print(f"
Left Join: {left_join.shape}")
print(f"الموظفين بدون تقييم: {left_join['تقييم_الأداء'].isna().sum()}")
# 3. Right Join - جميع الصفوف من الجدول الأيمن
right_join = df.merge(df_performance, on='الرقم_الوظيفي', how='right')
print(f"
Right Join: {right_join.shape}")
# 4. Outer Join - جميع الصفوف من كلا الجدولين
outer_join = df.merge(df_performance, on='الرقم_الوظيفي', how='outer')
print(f"
Outer Join: {outer_join.shape}")
# دمج مع جدول الأقسام
complete_data = left_join.merge(df_departments, on='القسم', how='left')
print(f"
البيانات الكاملة: {complete_data.shape}")
# عرض عينة من البيانات المدموجة
sample_columns = ['الاسم', 'القسم', 'الراتب', 'تقييم_الأداء', 'النقاط', 'المدير']
print(f"
عينة من البيانات المدموجة:")
print(complete_data[sample_columns].head(10))
دمج متقدم وتحليل شامل
# تحليل شامل للبيانات المدموجة
print("تحليل شامل للبيانات المدموجة:")
print("=" * 50)
# 1. تحليل الأداء حسب القسم
performance_by_dept = complete_data.groupby('القسم').agg({
'النقاط': ['mean', 'std', 'count'],
'الراتب': 'mean',
'العمر': 'mean'
}).round(2)
print("
1. الأداء حسب القسم:")
print(performance_by_dept)
# 2. العلاقة بين الراتب والأداء
salary_performance = complete_data.groupby('تقييم_الأداء').agg({
'الراتب': ['mean', 'median', 'count'],
'النقاط': 'mean',
'سنوات_الخبرة': 'mean'
}).round(2)
print("
2. العلاقة بين الراتب والأداء:")
print(salary_performance)
# 3. تحليل الكفاءة (النقاط مقابل الراتب)
complete_data['كفاءة_التكلفة'] = complete_data['النقاط'] / (complete_data['الراتب'] / 1000)
efficiency_by_dept = complete_data.groupby('القسم')['كفاءة_التكلفة'].agg([
'mean', 'median', 'std'
]).round(3)
print("
3. كفاءة التكلفة حسب القسم:")
print(efficiency_by_dept)
# 4. أفضل الموظفين أداءً
top_performers = complete_data.nlargest(10, 'النقاط')[
['الاسم', 'القسم', 'النقاط', 'تقييم_الأداء', 'الراتب', 'سنوات_الخبرة']
]
print("
4. أفضل 10 موظفين أداءً:")
print(top_performers)
# 5. الموظفين الذين يحتاجون تطوير
needs_improvement = complete_data[
(complete_data['النقاط'] < 70) |
(complete_data['تقييم_الأداء'] == 'مقبول')
][['الاسم', 'القسم', 'النقاط', 'تقييم_الأداء', 'سنوات_الخبرة']]
print(f"
5. الموظفين الذين يحتاجون تطوير ({len(needs_improvement)} موظف):")
print(needs_improvement.head())
💾 حفظ البيانات
بعد معالجة البيانات، نحتاج لحفظها بتنسيقات مختلفة:
حفظ بتنسيقات متعددة
# حفظ كملف CSV
complete_data.to_csv('employee_analysis.csv', index=False, encoding='utf-8')
print("تم حفظ البيانات كملف CSV")
# حفظ كملف Excel مع عدة أوراق عمل
with pd.ExcelWriter('employee_report.xlsx', engine='openpyxl') as writer:
# الورقة الأساسية
complete_data.to_excel(writer, sheet_name='البيانات_الكاملة', index=False)
# ورقة التحليل حسب القسم
performance_by_dept.to_excel(writer, sheet_name='تحليل_الأقسام')
# ورقة أفضل الموظفين
top_performers.to_excel(writer, sheet_name='أفضل_الموظفين', index=False)
# ورقة الموظفين المحتاجين تطوير
needs_improvement.to_excel(writer, sheet_name='يحتاج_تطوير', index=False)
print("تم حفظ التقرير الشامل كملف Excel")
# حفظ كملف JSON
complete_data.to_json('employee_data.json', orient='records', force_ascii=False)
print("تم حفظ البيانات كملف JSON")
# حفظ كملف Parquet (للبيانات الكبيرة)
complete_data.to_parquet('employee_data.parquet')
print("تم حفظ البيانات كملف Parquet")
# حفظ إحصائيات سريعة
summary_stats = {
'إجمالي_الموظفين': len(complete_data),
'متوسط_الراتب': complete_data['الراتب'].mean(),
'متوسط_النقاط': complete_data['النقاط'].mean(),
'عدد_الأقسام': complete_data['القسم'].nunique(),
'تاريخ_التحليل': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
summary_df = pd.DataFrame([summary_stats])
summary_df.to_csv('summary_stats.csv', index=False)
print("تم حفظ الإحصائيات الملخصة")
🎯 مثال عملي شامل: تحليل مبيعات متجر إلكتروني
الآن سنطبق جميع ما تعلمناه في مثال واقعي ومعقد:
إنشاء بيانات متجر إلكتروني
# إنشاء بيانات مبيعات متجر إلكتروني
np.random.seed(42)
# بيانات المنتجات
products = {
'معرف_المنتج': range(1, 101),
'اسم_المنتج': [f'منتج_{i}' for i in range(1, 101)],
'الفئة': np.random.choice(['إلكترونيات', 'ملابس', 'كتب', 'منزل', 'رياضة'], 100),
'السعر': np.random.uniform(50, 1000, 100).round(2),
'التكلفة': lambda: np.random.uniform(20, 500, 100).round(2)
}
products['التكلفة'] = np.random.uniform(20, 500, 100).round(2)
products['الربح'] = products['السعر'] - products['التكلفة']
df_products = pd.DataFrame(products)
# بيانات العملاء
customers = {
'معرف_العميل': range(1, 501),
'اسم_العميل': [f'عميل_{i}' for i in range(1, 501)],
'المدينة': np.random.choice(['الرياض', 'جدة', 'الدمام', 'مكة', 'المدينة'], 500),
'العمر': np.random.randint(18, 70, 500),
'الجنس': np.random.choice(['ذكر', 'أنثى'], 500),
'تاريخ_التسجيل': [datetime.now() - timedelta(days=np.random.randint(30, 1095)) for _ in range(500)]
}
df_customers = pd.DataFrame(customers)
# بيانات المبيعات
n_sales = 5000
sales = {
'معرف_الطلب': range(1, n_sales + 1),
'معرف_العميل': np.random.choice(df_customers['معرف_العميل'], n_sales),
'معرف_المنتج': np.random.choice(df_products['معرف_المنتج'], n_sales),
'الكمية': np.random.randint(1, 5, n_sales),
'تاريخ_الطلب': [datetime.now() - timedelta(days=np.random.randint(1, 365)) for _ in range(n_sales)],
'حالة_الطلب': np.random.choice(['مكتمل', 'ملغي', 'قيد المعالجة'], n_sales, p=[0.85, 0.10, 0.05])
}
df_sales = pd.DataFrame(sales)
print(f"المنتجات: {len(df_products)}")
print(f"العملاء: {len(df_customers)}")
print(f"المبيعات: {len(df_sales)}")
دمج البيانات وإنشاء التحليل الشامل
# دمج جميع البيانات
sales_complete = df_sales.merge(df_products, on='معرف_المنتج', how='left')
sales_complete = sales_complete.merge(df_customers, on='معرف_العميل', how='left')
# حساب المقاييس المالية
sales_complete['إجمالي_السعر'] = sales_complete['السعر'] * sales_complete['الكمية']
sales_complete['إجمالي_التكلفة'] = sales_complete['التكلفة'] * sales_complete['الكمية']
sales_complete['إجمالي_الربح'] = sales_complete['إجمالي_السعر'] - sales_complete['إجمالي_التكلفة']
# إضافة معلومات زمنية
sales_complete['الشهر'] = sales_complete['تاريخ_الطلب'].dt.month
sales_complete['اليوم_من_الأسبوع'] = sales_complete['تاريخ_الطلب'].dt.day_name()
sales_complete['الربع'] = sales_complete['تاريخ_الطلب'].dt.quarter
# فلترة الطلبات المكتملة فقط للتحليل
completed_sales = sales_complete[sales_complete['حالة_الطلب'] == 'مكتمل'].copy()
print(f"إجمالي الطلبات: {len(sales_complete)}")
print(f"الطلبات المكتملة: {len(completed_sales)}")
print(f"معدل إتمام الطلبات: {len(completed_sales)/len(sales_complete)*100:.1f}%")
التحليل المالي الشامل
print("📊 التحليل المالي الشامل")
print("=" * 50)
# 1. الأداء المالي العام
total_revenue = completed_sales['إجمالي_السعر'].sum()
total_cost = completed_sales['إجمالي_التكلفة'].sum()
total_profit = completed_sales['إجمالي_الربح'].sum()
profit_margin = (total_profit / total_revenue) * 100
print(f"
💰 الأداء المالي العام:")
print(f"إجمالي الإيرادات: {total_revenue:,.2f} ريال")
print(f"إجمالي التكاليف: {total_cost:,.2f} ريال")
print(f"إجمالي الأرباح: {total_profit:,.2f} ريال")
print(f"هامش الربح: {profit_margin:.1f}%")
# 2. الأداء حسب الفئة
category_performance = completed_sales.groupby('الفئة').agg({
'إجمالي_السعر': 'sum',
'إجمالي_الربح': 'sum',
'الكمية': 'sum',
'معرف_الطلب': 'count'
}).round(2)
category_performance['هامش_الربح'] = (
category_performance['إجمالي_الربح'] / category_performance['إجمالي_السعر'] * 100
).round(1)
category_performance.columns = ['الإيرادات', 'الأرباح', 'الكمية_المباعة', 'عدد_الطلبات', 'هامش_الربح_%']
category_performance = category_performance.sort_values('الإيرادات', ascending=False)
print(f"
📈 الأداء حسب الفئة:")
print(category_performance)
# 3. الأداء الشهري
monthly_performance = completed_sales.groupby('الشهر').agg({
'إجمالي_السعر': 'sum',
'إجمالي_الربح': 'sum',
'معرف_الطلب': 'count'
}).round(2)
monthly_performance.columns = ['الإيرادات', 'الأرباح', 'عدد_الطلبات']
print(f"
📅 الأداء الشهري:")
print(monthly_performance)
# 4. أفضل المنتجات
top_products = completed_sales.groupby(['معرف_المنتج', 'اسم_المنتج']).agg({
'إجمالي_السعر': 'sum',
'إجمالي_الربح': 'sum',
'الكمية': 'sum'
}).round(2).sort_values('إجمالي_السعر', ascending=False).head(10)
print(f"
🏆 أفضل 10 منتجات (حسب الإيرادات):")
print(top_products)
تحليل العملاء المتقدم
print("
👥 تحليل العملاء المتقدم")
print("=" * 50)
# 1. تحليل سلوك العملاء
customer_behavior = completed_sales.groupby('معرف_العميل').agg({
'إجمالي_السعر': ['sum', 'mean', 'count'],
'الكمية': 'sum',
'تاريخ_الطلب': ['min', 'max']
}).round(2)
# تسطيح أسماء الأعمدة
customer_behavior.columns = ['إجمالي_الإنفاق', 'متوسط_الطلب', 'عدد_الطلبات', 'إجمالي_الكمية', 'أول_طلب', 'آخر_طلب']
# حساب قيمة العميل مدى الحياة (CLV)
customer_behavior['قيمة_العميل'] = customer_behavior['إجمالي_الإنفاق']
# تصنيف العملاء
customer_behavior['فئة_العميل'] = pd.cut(
customer_behavior['قيمة_العميل'],
bins=[0, 500, 1500, 5000, float('inf')],
labels=['عادي', 'جيد', 'مميز', 'VIP']
)
# إحصائيات العملاء
print(f"
📊 إحصائيات العملاء:")
print(f"إجمالي العملاء النشطين: {len(customer_behavior)}")
print(f"متوسط قيمة العميل: {customer_behavior['قيمة_العميل'].mean():.2f} ريال")
print(f"متوسط عدد الطلبات للعميل: {customer_behavior['عدد_الطلبات'].mean():.1f}")
# توزيع فئات العملاء
customer_segments = customer_behavior['فئة_العميل'].value_counts()
print(f"
🎯 توزيع فئات العملاء:")
print(customer_segments)
# أفضل العملاء
top_customers = customer_behavior.nlargest(10, 'قيمة_العميل')[
['إجمالي_الإنفاق', 'عدد_الطلبات', 'متوسط_الطلب', 'فئة_العميل']
]
print(f"
🌟 أفضل 10 عملاء:")
print(top_customers)
# 2. التحليل الجغرافي
geographic_analysis = completed_sales.groupby('المدينة').agg({
'إجمالي_السعر': 'sum',
'معرف_العميل': 'nunique',
'معرف_الطلب': 'count'
}).round(2)
geographic_analysis.columns = ['إجمالي_الإيرادات', 'عدد_العملاء', 'عدد_الطلبات']
geographic_analysis['متوسط_الإنفاق_للعميل'] = (
geographic_analysis['إجمالي_الإيرادات'] / geographic_analysis['عدد_العملاء']
).round(2)
geographic_analysis = geographic_analysis.sort_values('إجمالي_الإيرادات', ascending=False)
print(f"
🗺️ التحليل الجغرافي:")
print(geographic_analysis)
# 3. تحليل الأعمار والجنس
demographic_analysis = completed_sales.groupby(['الجنس', pd.cut(completed_sales['العمر'], bins=[0, 25, 35, 50, 100], labels=['18-25', '26-35', '36-50', '50+'])]).agg({
'إجمالي_السعر': 'sum',
'معرف_العميل': 'nunique'
}).round(2)
print(f"
👫 التحليل الديموغرافي:")
print(demographic_analysis)
🎯 ماذا تعلمنا من هذا المثال الشامل؟
- إنشاء البيانات: محاكاة بيانات واقعية لمتجر إلكتروني
- دمج البيانات: ربط جداول المنتجات والعملاء والمبيعات
- المقاييس المالية: حساب الإيرادات والأرباح وهوامش الربح
- التحليل الزمني: الأداء الشهري والربعي
- تصنيف العملاء: تقسيم العملاء حسب القيمة
- التحليل الجغرافي: الأداء حسب المدن
- التحليل الديموغرافي: سلوك الشراء حسب العمر والجنس
🎯 تمارين عملية
تمرين 1: تحليل بيانات الطلاب
أنشئ وحلل بيانات 500 طالب:
- معلومات شخصية (الاسم، العمر، الجنس، المدينة)
- معلومات أكاديمية (التخصص، المستوى، المعدل)
- حلل الأداء حسب التخصص والمدينة
- اعثر على الطلاب المتفوقين والمحتاجين مساعدة
تمرين 2: تحليل بيانات الأسهم
اقرأ بيانات أسعار الأسهم وحللها:
- اقرأ بيانات تاريخية لـ 5 أسهم
- احسب العوائد اليومية والشهرية
- حلل التقلبات والمخاطر
- أنشئ محفظة استثمارية متوازنة
تمرين 3: تحليل بيانات وسائل التواصل
حلل بيانات منصة تواصل اجتماعي:
- بيانات المستخدمين والمنشورات
- تحليل المشاركة والتفاعل
- اكتشاف الاتجاهات والمواضيع الرائجة
- تحليل سلوك المستخدمين
⚡ نصائح الأداء الأمثل
⚠️ أخطاء شائعة يجب تجنبها:
- تجاهل أنواع البيانات: تحقق من dtypes دائماً
- عدم التعامل مع القيم المفقودة: قد تؤثر على النتائج
- استخدام الحلقات: استخدم العمليات المتجهة
- تجاهل الفهارس: قد تسبب مشاكل في الدمج
📝 ملخص الدرس
في هذا الدرس الشامل تعلمنا:
- ✅ ما هو Pandas: أقوى مكتبة لمعالجة البيانات
- ✅ هياكل البيانات: Series وDataFrame
- ✅ قراءة البيانات: CSV وExcel وJSON وقواعد البيانات
- ✅ استكشاف البيانات: الإحصائيات والمعلومات الأساسية
- ✅ الفهرسة والتقطيع: الوصول المتقدم للبيانات
- ✅ تنظيف البيانات: القيم المفقودة والتكرارات
- ✅ التحليل والتجميع: GroupBy والجداول المحورية
- ✅ دمج البيانات: Join وMerge
- ✅ حفظ البيانات: تنسيقات متعددة
- ✅ مثال عملي شامل: تحليل متجر إلكتروني
➡️ الدرس التالي
في الدرس التالي سنتعلم Matplotlib وSeaborn للتصور:
- إنشاء الرسوم البيانية الأساسية
- التصور الإحصائي المتقدم
- تخصيص الألوان والأنماط
- إنشاء لوحات معلومات تفاعلية
- أفضل ممارسات التصور
- تصدير الرسوم بجودة عالية