Spaces:
Sleeping
Sleeping
import pandas as pd | |
import numpy as np | |
from sklearn.cluster import KMeans | |
from sklearn.preprocessing import StandardScaler | |
import matplotlib.pyplot as plt | |
import seaborn as sns | |
import os | |
from collections import Counter | |
def create_audience_segments(audience_data): | |
""" | |
إنشاء شرائح الجمهور باستخدام التعلم الآلي | |
""" | |
try: | |
# تحويل البيانات إلى DataFrame | |
if not isinstance(audience_data, pd.DataFrame): | |
audience_data = pd.DataFrame(audience_data) | |
# التحقق من وجود بيانات | |
if audience_data.empty: | |
print("بيانات الجمهور فارغة") | |
return None | |
# تحديد الميزات الرقمية للتصنيف | |
numeric_features = [] | |
for col in ['booking_frequency', 'avg_stay_duration', 'price_sensitivity', 'response_rate']: | |
if col in audience_data.columns: | |
numeric_features.append(col) | |
# التحقق من وجود ميزات كافية | |
if not numeric_features: | |
print("لا توجد ميزات رقمية كافية للتصنيف") | |
return None | |
# استخراج الميزات الرقمية | |
X = audience_data[numeric_features].values | |
# تطبيع البيانات | |
scaler = StandardScaler() | |
X_scaled = scaler.fit_transform(X) | |
# تحديد عدد المجموعات المثالي (يمكن تحسينه باستخدام طريقة Elbow) | |
n_clusters = min(4, len(audience_data)) | |
# استخدام K-means للتصنيف | |
kmeans = KMeans(n_clusters=n_clusters, random_state=42) | |
clusters = kmeans.fit_predict(X_scaled) | |
# إضافة معرفات المجموعات إلى البيانات الأصلية | |
audience_data['cluster'] = clusters | |
return { | |
'segmented_data': audience_data, | |
'kmeans_model': kmeans, | |
'scaler': scaler, | |
'features': numeric_features | |
} | |
except Exception as e: | |
print(f"خطأ في إنشاء شرائح الجمهور: {str(e)}") | |
return None | |
def analyze_audience_segments(segmented_data): | |
""" | |
تحليل شرائح الجمهور وإرجاع خصائص كل شريحة | |
""" | |
try: | |
# التحقق من وجود بيانات | |
if not isinstance(segmented_data, pd.DataFrame) or 'cluster' not in segmented_data.columns: | |
print("البيانات غير صالحة للتحليل") | |
return {} | |
segments = {} | |
for cluster_id in segmented_data['cluster'].unique(): | |
cluster_data = segmented_data[segmented_data['cluster'] == cluster_id] | |
# تحليل خصائص الشريحة | |
segment_profile = { | |
'size': len(cluster_data), | |
'avg_booking_frequency': cluster_data['booking_frequency'].mean() if 'booking_frequency' in cluster_data.columns else 0, | |
'avg_stay_duration': cluster_data['avg_stay_duration'].mean() if 'avg_stay_duration' in cluster_data.columns else 0, | |
'price_sensitivity': cluster_data['price_sensitivity'].mean() if 'price_sensitivity' in cluster_data.columns else 0, | |
'response_rate': cluster_data['response_rate'].mean() if 'response_rate' in cluster_data.columns else 0 | |
} | |
# إضافة توزيع الفئات العمرية إذا كانت موجودة | |
if 'age_range' in cluster_data.columns: | |
segment_profile['age_distribution'] = cluster_data['age_range'].value_counts().to_dict() | |
# إضافة توزيع الحالة العائلية إذا كانت موجودة | |
if 'family_status' in cluster_data.columns: | |
segment_profile['family_status_distribution'] = cluster_data['family_status'].value_counts().to_dict() | |
# إضافة توزيع الاهتمامات إذا كانت موجودة | |
if 'interests' in cluster_data.columns: | |
all_interests = [] | |
for interests_str in cluster_data['interests']: | |
if isinstance(interests_str, str): | |
interests = [i.strip() for i in interests_str.split(',')] | |
all_interests.extend(interests) | |
interest_counts = Counter(all_interests) | |
# ترتيب الاهتمامات حسب الشيوع | |
sorted_interests = sorted(interest_counts.items(), key=lambda x: x[1], reverse=True) | |
segment_profile['top_interests'] = {k: v for k, v in sorted_interests[:5]} if sorted_interests else {} | |
segments[f'Segment {cluster_id}'] = segment_profile | |
return segments | |
except Exception as e: | |
print(f"خطأ في تحليل شرائح الجمهور: {str(e)}") | |
return {} | |
def create_segment_visualization(segmented_data, features): | |
""" | |
إنشاء رسوم بيانية لتوضيح شرائح الجمهور | |
""" | |
try: | |
# التحقق من وجود بيانات | |
if not isinstance(segmented_data, pd.DataFrame) or 'cluster' not in segmented_data.columns: | |
print("البيانات غير صالحة للتصور") | |
fig, ax = plt.subplots(figsize=(8, 6)) | |
ax.text(0.5, 0.5, 'لا توجد بيانات كافية لإنشاء الرسوم البيانية', | |
horizontalalignment='center', verticalalignment='center', transform=ax.transAxes) | |
return fig | |
# التحقق من وجود الميزات | |
valid_features = [f for f in features if f in segmented_data.columns] | |
if len(valid_features) < 2: | |
print("لا توجد ميزات كافية للتصور") | |
fig, ax = plt.subplots(figsize=(8, 6)) | |
ax.text(0.5, 0.5, 'لا توجد ميزات كافية لإنشاء الرسوم البيانية', | |
horizontalalignment='center', verticalalignment='center', transform=ax.transAxes) | |
return fig | |
# إنشاء الرسوم البيانية | |
fig, axes = plt.subplots(2, 2, figsize=(12, 10)) | |
# تعيين نمط الخط لدعم اللغة العربية | |
plt.rcParams['font.family'] = 'Arial' | |
# رسم توزيع تكرار الحجز حسب الشريحة | |
if 'booking_frequency' in valid_features: | |
sns.boxplot(x='cluster', y='booking_frequency', data=segmented_data, ax=axes[0, 0]) | |
axes[0, 0].set_title('توزيع تكرار الحجز حسب الشريحة') | |
axes[0, 0].set_ylabel('تكرار الحجز') | |
axes[0, 0].set_xlabel('الشريحة') | |
else: | |
axes[0, 0].text(0.5, 0.5, 'لا توجد بيانات لتكرار الحجز', | |
horizontalalignment='center', verticalalignment='center', transform=axes[0, 0].transAxes) | |
# رسم توزيع مدة الإقامة حسب الشريحة | |
if 'avg_stay_duration' in valid_features: | |
sns.boxplot(x='cluster', y='avg_stay_duration', data=segmented_data, ax=axes[0, 1]) | |
axes[0, 1].set_title('توزيع مدة الإقامة حسب الشريحة') | |
axes[0, 1].set_ylabel('متوسط مدة الإقامة (أيام)') | |
axes[0, 1].set_xlabel('الشريحة') | |
else: | |
axes[0, 1].text(0.5, 0.5, 'لا توجد بيانات لمدة الإقامة', | |
horizontalalignment='center', verticalalignment='center', transform=axes[0, 1].transAxes) | |
# رسم توزيع حساسية السعر حسب الشريحة | |
if 'price_sensitivity' in valid_features: | |
sns.boxplot(x='cluster', y='price_sensitivity', data=segmented_data, ax=axes[1, 0]) | |
axes[1, 0].set_title('توزيع حساسية السعر حسب الشريحة') | |
axes[1, 0].set_ylabel('حساسية السعر (0-1)') | |
axes[1, 0].set_xlabel('الشريحة') | |
else: | |
axes[1, 0].text(0.5, 0.5, 'لا توجد بيانات لحساسية السعر', | |
horizontalalignment='center', verticalalignment='center', transform=axes[1, 0].transAxes) | |
# رسم توزيع معدل الاستجابة حسب الشريحة | |
if 'response_rate' in valid_features: | |
sns.boxplot(x='cluster', y='response_rate', data=segmented_data, ax=axes[1, 1]) | |
axes[1, 1].set_title('توزيع معدل الاستجابة حسب الشريحة') | |
axes[1, 1].set_ylabel('معدل الاستجابة') | |
axes[1, 1].set_xlabel('الشريحة') | |
else: | |
axes[1, 1].text(0.5, 0.5, 'لا توجد بيانات لمعدل الاستجابة', | |
horizontalalignment='center', verticalalignment='center', transform=axes[1, 1].transAxes) | |
plt.tight_layout() | |
return fig | |
except Exception as e: | |
print(f"خطأ في إنشاء الرسوم البيانية: {str(e)}") | |
fig, ax = plt.subplots(figsize=(8, 6)) | |
ax.text(0.5, 0.5, f'خطأ في إنشاء الرسوم البيانية: {str(e)}', | |
horizontalalignment='center', verticalalignment='center', transform=ax.transAxes) | |
return fig | |
def generate_targeted_content(chalet_data, segment_profile): | |
""" | |
توليد محتوى مستهدف بناءً على ملف تعريف الشريحة | |
""" | |
try: | |
# التحقق من وجود بيانات | |
if not isinstance(chalet_data, dict) or not isinstance(segment_profile, dict): | |
print("البيانات غير صالحة لتوليد المحتوى") | |
return {} | |
content_recommendations = {} | |
# تحديد نوع المحتوى المناسب | |
if 'price_sensitivity' in segment_profile and segment_profile['price_sensitivity'] > 0.7: | |
content_recommendations['content_type'] = 'قيمة وتوفير' | |
content_recommendations['key_messages'] = [ | |
f"قيمة استثنائية في {chalet_data.get('location', 'الموقع')}", | |
"أسعار تنافسية مع خدمات ممتازة", | |
"عروض خاصة للإقامات الطويلة" | |
] | |
elif 'avg_stay_duration' in segment_profile and segment_profile['avg_stay_duration'] > 5: | |
content_recommendations['content_type'] = 'إقامة طويلة' | |
content_recommendations['key_messages'] = [ | |
f"استمتع بإقامة مريحة وطويلة في {chalet_data.get('name', 'الشاليه')}", | |
"مرافق متكاملة للإقامات الطويلة", | |
"خصومات خاصة للإقامات الأسبوعية والشهرية" | |
] | |
elif 'top_interests' in segment_profile and any(interest in str(segment_profile['top_interests']).lower() for interest in ['عائلة', 'أطفال', 'family']): | |
content_recommendations['content_type'] = 'عائلي' | |
content_recommendations['key_messages'] = [ | |
f"عطلة عائلية مثالية في {chalet_data.get('name', 'الشاليه')}", | |
"أنشطة ترفيهية للأطفال والكبار", | |
"مساحات آمنة ومريحة للعائلات" | |
] | |
else: | |
content_recommendations['content_type'] = 'فاخر' | |
content_recommendations['key_messages'] = [ | |
f"تجربة فاخرة في {chalet_data.get('name', 'الشاليه')}", | |
"مرافق حصرية ومميزة", | |
"خدمة شخصية على أعلى مستوى" | |
] | |
# تحديد الصور المناسبة | |
if content_recommendations['content_type'] == 'عائلي': | |
content_recommendations['image_focus'] = ['مساحات عائلية', 'ملاعب أطفال', 'مسبح آمن'] | |
elif content_recommendations['content_type'] == 'فاخر': | |
content_recommendations['image_focus'] = ['تصميم داخلي فاخر', 'إطلالة مميزة', 'مرافق حصرية'] | |
elif content_recommendations['content_type'] == 'قيمة وتوفير': | |
content_recommendations['image_focus'] = ['المرافق الأساسية', 'المساحات المشتركة', 'موقع مميز'] | |
else: | |
content_recommendations['image_focus'] = ['المساحات الواسعة', 'المطبخ المجهز', 'مناطق العمل'] | |
# تحديد قنوات التسويق المناسبة | |
if 'response_rate' in segment_profile and segment_profile['response_rate'] > 0.15: | |
content_recommendations['marketing_channels'] = ['إعلانات فيسبوك', 'إنستغرام', 'البريد الإلكتروني'] | |
else: | |
content_recommendations['marketing_channels'] = ['منصات حجز السفر', 'جوجل', 'مواقع المراجعات'] | |
return content_recommendations | |
except Exception as e: | |
print(f"خطأ في توليد المحتوى المستهدف: {str(e)}") | |
return {} | |
def load_audience_data_from_file(file_path): | |
""" | |
تحميل بيانات الجمهور من ملف | |
""" | |
try: | |
if not os.path.exists(file_path): | |
print(f"الملف {file_path} غير موجود") | |
return pd.DataFrame() | |
# تحديد نوع الملف | |
if file_path.endswith('.csv'): | |
df = pd.read_csv(file_path) | |
elif file_path.endswith('.xlsx'): | |
df = pd.read_excel(file_path) | |
else: | |
print(f"نوع الملف غير مدعوم: {file_path}") | |
return pd.DataFrame() | |
return df | |
except Exception as e: | |
print(f"خطأ في تحميل بيانات الجمهور: {str(e)}") | |
return pd.DataFrame() | |
def save_audience_segments(segmented_data, file_path): | |
""" | |
حفظ شرائح الجمهور في ملف | |
""" | |
try: | |
# التحقق من وجود بيانات | |
if not isinstance(segmented_data, pd.DataFrame) or segmented_data.empty: | |
print("البيانات فارغة أو غير صالحة") | |
return False | |
# تحديد نوع الملف | |
if file_path.endswith('.csv'): | |
segmented_data.to_csv(file_path, index=False) | |
elif file_path.endswith('.xlsx'): | |
segmented_data.to_excel(file_path, index=False) | |
else: | |
print(f"نوع الملف غير مدعوم: {file_path}") | |
return False | |
return True | |
except Exception as e: | |
print(f"خطأ في حفظ شرائح الجمهور: {str(e)}") | |
return False | |
def extract_audience_from_bookings(bookings_data): | |
""" | |
استخراج بيانات الجمهور من بيانات الحجوزات | |
""" | |
try: | |
# التحقق من وجود بيانات | |
if not isinstance(bookings_data, pd.DataFrame) or bookings_data.empty: | |
print("بيانات الحجوزات فارغة أو غير صالحة") | |
return pd.DataFrame() | |
# código existente... | |
# Aquí está el problema, la función termina abruptamente | |
bookings | |
# Debe completarse con algo como: | |
return audience_data | |
except Exception as e: | |
print(f"خطأ في استخراج بيانات الجمهور: {str(e)}") | |
return pd.DataFrame() | |