{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":17000,"databundleVersionId":895292,"sourceType":"competition"}],"dockerImageVersionId":31153,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-10-23T07:25:32.464609Z","iopub.execute_input":"2025-10-23T07:25:32.464995Z","iopub.status.idle":"2025-10-23T07:25:32.472166Z","shell.execute_reply.started":"2025-10-23T07:25:32.464968Z","shell.execute_reply":"2025-10-23T07:25:32.470943Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 🐱 Cat-in-the-Dat II - Exploratory Data Analysis (EDA)\n# ============================================================\n\n# 1️⃣ استيراد المكتبات\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.preprocessing import LabelEncoder\n\n\n# 3️⃣ فحص المعلومات العامة\nprint(\"\\n--- Info ---\")\ntrain.info()\n\n# 4️⃣ القيم المفقودة\nmissing = train.isnull().mean().sort_values(ascending=False)\nprint(\"\\n--- Missing Values ---\")\nprint(missing[missing > 0])\n\n\n\n# 5️⃣ تحليل المتغير الهدف\nprint(\"\\n--- Target distribution ---\")\nprint(train['target'].value_counts(normalize=True))\nsns.countplot(x='target', data=train)\nplt.title(\"Target Distribution\")\nplt.show()\n\n# 6️⃣ تحديد أنواع المتغيرات\nbinary_features = [c for c in train.columns if 'bin' in c]\nnominal_features = [c for c in train.columns if 'nom' in c]\nordinal_features = [c for c in train.columns if 'ord' in c]\ntemporal_features = ['day', 'month']\n\nprint(f\"\\nBinary features: {len(binary_features)}\")\nprint(f\"Nominal features: {len(nominal_features)}\")\nprint(f\"Ordinal features: {len(ordinal_features)}\")\nprint(f\"Temporal features: {temporal_features}\")\n\n# 7️⃣ تحليل المتغيرات الثنائية (Binary)\nfor col in binary_features:\n    sns.countplot(x=col, data=train)\n    plt.title(f\"{col} distribution\")\n    plt.show()\n\n# 8️⃣ تحليل المتغيرات الاسمية (Nominal)\nprint(\"\\n--- Unique categories per nominal feature ---\")\nfor col in nominal_features:\n    print(f\"{col}: {train[col].nunique()} unique values\")\n\n\n# 1️⃣3️⃣ التجهيز للنمذجة\nX = train.drop(columns=['target', 'id'])\ny = train['target']\n\nprint(\"\\n✅ Data ready for modeling!\")\nprint(\"Features shape:\", X.shape)\nprint(\"Target shape:\", y.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T16:44:17.018233Z","iopub.execute_input":"2025-10-23T16:44:17.018578Z","iopub.status.idle":"2025-10-23T16:44:20.044513Z","shell.execute_reply.started":"2025-10-23T16:44:17.018553Z","shell.execute_reply":"2025-10-23T16:44:20.043514Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score\nfrom lightgbm import LGBMClassifier\n\ntrain = pd.read_csv(\"/kaggle/input/cat-in-the-dat-ii/train.csv\")\ntest = pd.read_csv(\"/kaggle/input/cat-in-the-dat-ii/test.csv\")\nimport warnings\nwarnings.filterwarnings(\"ignore\", category=RuntimeWarning)\n\ntrain.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T14:16:36.800829Z","iopub.execute_input":"2025-10-23T14:16:36.801182Z","iopub.status.idle":"2025-10-23T14:16:47.573999Z","shell.execute_reply.started":"2025-10-23T14:16:36.801159Z","shell.execute_reply":"2025-10-23T14:16:47.572971Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\n\n\n\n# تحديد الأعمدة الفئوية\nbinary_features = [c for c in train.columns if 'bin' in c]\nnominal_features = [c for c in train.columns if 'nom' in c]\nordinal_features = [c for c in train.columns if 'ord' in c]\ntemporal_features = ['day', 'month']\nfeatures = binary_features + nominal_features + ordinal_features + temporal_features\n\n# 🔹 الحل: دمج train + test للترميز\nfull_data = pd.concat([train[features], test[features]], axis=0)\n\n# 🔸 تطبيق LabelEncoder على البيانات المدمجة\nfor col in features:\n    le = LabelEncoder()\n    full_data[col] = le.fit_transform(full_data[col].astype(str))\n\n# 🔹 تقسيمها من جديد بعد الترميز\ntrain[features] = full_data.iloc[:len(train)][features]\ntest[features] = full_data.iloc[len(train):][features]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T16:45:09.713124Z","iopub.execute_input":"2025-10-23T16:45:09.713468Z","iopub.status.idle":"2025-10-23T16:45:20.853459Z","shell.execute_reply.started":"2025-10-23T16:45:09.713444Z","shell.execute_reply":"2025-10-23T16:45:20.85248Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/cat-in-the-dat-ii/train.csv')\n\nfor col in df.columns:\n    unique_vals = df[col].unique()\n    print(f\"Unique values in '{col}':\")\n    print(unique_vals)\n    print(f\"Count: {len(unique_vals)}\")\n    print(\"-\" * 40)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T16:45:25.330556Z","iopub.execute_input":"2025-10-23T16:45:25.330981Z","iopub.status.idle":"2025-10-23T16:45:28.084106Z","shell.execute_reply.started":"2025-10-23T16:45:25.330948Z","shell.execute_reply":"2025-10-23T16:45:28.083061Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\ndf = pd.read_csv('/kaggle/input/cat-in-the-dat-ii/train.csv')\n\nmissing_counts = df.isnull().sum()\nprint(missing_counts)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T16:45:37.475841Z","iopub.execute_input":"2025-10-23T16:45:37.476134Z","iopub.status.idle":"2025-10-23T16:45:40.273798Z","shell.execute_reply.started":"2025-10-23T16:45:37.476112Z","shell.execute_reply":"2025-10-23T16:45:40.272868Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"value_counts = df['nom_7'].value_counts(dropna=False)\nprint(\"Top 10 most frequent values in 'nom_7':\")\nprint(value_counts.head(10))\n\n# 2. تعويض القيم الناقصة بقيمة \"Missing\"\nmissing_before = df['nom_7'].isnull().sum()\nprint(f\"\\nMissing values before filling: {missing_before}\")\n\ndf['nom_7'].fillna('Missing', inplace=True)\n\nmissing_after = df['nom_7'].isnull().sum()\nprint(f\"Missing values after filling: {missing_after}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T16:45:44.642889Z","iopub.execute_input":"2025-10-23T16:45:44.643529Z","iopub.status.idle":"2025-10-23T16:45:44.76846Z","shell.execute_reply.started":"2025-10-23T16:45:44.643501Z","shell.execute_reply":"2025-10-23T16:45:44.767534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\n# تحديد الأعمدة التصنيفية (categorical) حسب معرفة مسبقة أو حسب نوع الداتا\ncategorical_features = df.select_dtypes(include=['object']).columns.tolist()\n\nprint(\"Categorical Features:\", categorical_features)\n\n# تعويض القيم الناقصة\nfor col in categorical_features:\n    unique_vals = df[col].dropna().unique()\n    if len(unique_vals) == 0:\n        # إذا العمود كله ناقص نملأه بقيمة ثابتة\n        df[col].fillna('Missing', inplace=True)\n        continue\n\n    # مثال: تعويض بالقيمة الأكثر تكرارًا (mode)\n    mode_val = df[col].mode()[0]\n\n    # بديل: تعويض بقيمة عشوائية من القيم الفريدة (لو حابب)\n    # random_val = np.random.choice(unique_vals)\n\n    df[col].fillna(mode_val, inplace=True)\n\nprint(\"Missing values after imputation:\")\nprint(df[categorical_features].isnull().sum())\n\n# --- Feature Engineering ---\n\n# 1. تحويل الأعمدة الثنائية binary إلى 0 و 1 (لو فيها)\n# عادةً تكون قيمها 'T'/'F' أو 'Y'/'N' أو '0'/'1' نص\nbinary_map = {\n    'T': 1,\n    'F': 0,\n    'Y': 1,\n    'N': 0,\n    'Yes': 1,\n    'No': 0,\n    'true': 1,\n    'false': 0,\n    'True': 1,\n    'False': 0,\n    '0': 0,\n    '1': 1,\n}\n\nfor col in categorical_features:\n    if df[col].nunique() == 2:\n        # حاول تحويل القيم حسب القاموس\n        df[col] = df[col].map(binary_map).astype('float')\n        # لو لم يتحول بالكامل، نستخدم Label Encoding بسيط\n        if df[col].isnull().sum() > 0:\n            df[col] = pd.factorize(df[col].astype(str))[0]\n\n# 2. ترميز الخصائص التصنيفية الأخرى باستخدام Frequency Encoding\nfor col in categorical_features:\n    if df[col].dtype == 'object':\n        freq_encoding = df[col].value_counts(normalize=True)\n        df[col + '_freq_enc'] = df[col].map(freq_encoding)\n\n# 3. إزالة الأعمدة الأصلية النصية بعد الترميز (اختياري)\n# df.drop(columns=categorical_features, inplace=True)\n\nprint(\"Feature Engineering done.\")\n\n# حفظ الداتا بعد المعالجة (اختياري)\n# df.to_csv('train_processed.csv', index=False)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T16:45:55.211096Z","iopub.execute_input":"2025-10-23T16:45:55.211765Z","iopub.status.idle":"2025-10-23T16:46:00.018474Z","shell.execute_reply.started":"2025-10-23T16:45:55.211731Z","shell.execute_reply":"2025-10-23T16:46:00.017489Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"importances = model.feature_importances_\nfeatures = X_train_enc.columns\n\nfi_df = pd.DataFrame({'Feature': features, 'Importance': importances})\nfi_df = fi_df.sort_values(by='Importance', ascending=False)\n\nplt.figure(figsize=(10,6))\nplt.barh(fi_df['Feature'], fi_df['Importance'])\nplt.gca().invert_yaxis()\nplt.title('Feature Importance (Random Forest)')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T17:06:02.580253Z","iopub.execute_input":"2025-10-23T17:06:02.58111Z","iopub.status.idle":"2025-10-23T17:06:03.118212Z","shell.execute_reply.started":"2025-10-23T17:06:02.581074Z","shell.execute_reply":"2025-10-23T17:06:03.117255Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.model_selection import train_test_split\ndf.to_csv('train_processed.csv', index=False)\n\n# قراءة البيانات (بعد المعالجة اللي سويناها)\ndf = pd.read_csv('train_processed.csv')  # لو ما حفظتها، خذ df من الخطوة السابقة مباشرة\n\n# فصل المتغير الهدف (target) والميزات (features)\ntarget = 'target'  # غيره حسب اسم العمود المستهدف عندك\nX = df.drop(columns=[target])\ny = df[target]\n\n# تقسيم البيانات إلى تدريب واختبار (مثلاً 80% تدريب و20% اختبار)\nX_train, X_val, y_train, y_val = train_test_split(\n    X, y, test_size=0.2, random_state=42, stratify=y\n)\n\nprint(f\"Training samples: {len(X_train)}, Validation samples: {len(X_val)}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T16:46:20.571453Z","iopub.execute_input":"2025-10-23T16:46:20.571761Z","iopub.status.idle":"2025-10-23T16:46:47.032553Z","shell.execute_reply.started":"2025-10-23T16:46:20.571739Z","shell.execute_reply":"2025-10-23T16:46:47.031554Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.impute import SimpleImputer\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.model_selection import train_test_split\n\n# نفترض df جاهز ومعالج القيم الناقصة الأصلية (مثلاً: استبدال NaN بقيمة جديدة)\n\n# افصل المتغير الهدف والميزات\ntarget = 'target'\nX = df.drop(columns=[target])\ny = df[target]\n\n# قسم البيانات\nX_train, X_val, y_train, y_val = train_test_split(\n    X, y, test_size=0.2, random_state=42, stratify=y\n)\n\n# ترميز الخصائص الفئوية\ncategorical_features = X_train.select_dtypes(include=['object']).columns\n\nX_train_enc = X_train.copy()\nX_val_enc = X_val.copy()\n\nlabel_encoders = {}\n\nfor col in categorical_features:\n    le = LabelEncoder()\n    # تحويل NaN إلى نص 'missing' قبل الترميز (حتى لا يفشل الترميز)\n    X_train_enc[col] = X_train_enc[col].fillna('missing').astype(str)\n    le.fit(X_train_enc[col])\n    X_train_enc[col] = le.transform(X_train_enc[col])\n    \n    # حفظ الـ encoder لكل عمود\n    label_encoders[col] = le\n\n    # نفس العملية لبيانات التحقق، مع تعويض NaN ب'missing'\n    X_val_enc[col] = X_val_enc[col].fillna('missing').astype(str)\n    # تعويض القيم غير المعروفة برقم خاص (مثلاً -1)\n    X_val_enc[col] = X_val_enc[col].map(lambda s: le.transform([s])[0] if s in le.classes_ else -1)\n\n# تعويض القيم الناقصة الرقمية (إن وجدت) بعد الترميز\nimputer = SimpleImputer(strategy='median')\nX_train_enc = pd.DataFrame(imputer.fit_transform(X_train_enc), columns=X_train_enc.columns)\nX_val_enc = pd.DataFrame(imputer.transform(X_val_enc), columns=X_val_enc.columns)\n\n# تدريب النموذج\nmodel = RandomForestClassifier(n_estimators=100, random_state=42)\nmodel.fit(X_train_enc, y_train)\n\n# تقييم النموذج\nprint(\"Training accuracy:\", model.score(X_train_enc, y_train))\nprint(\"Validation accuracy:\", model.score(X_val_enc, y_val))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T16:47:01.227277Z","iopub.execute_input":"2025-10-23T16:47:01.227622Z","iopub.status.idle":"2025-10-23T16:57:30.558425Z","shell.execute_reply.started":"2025-10-23T16:47:01.227599Z","shell.execute_reply":"2025-10-23T16:57:30.557146Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\n\ny_val_pred = model.predict(X_val_enc)\n\nprint(\"Classification Report:\\n\", classification_report(y_val, y_val_pred))\nprint(\"Confusion Matrix:\\n\", confusion_matrix(y_val, y_val_pred))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T17:05:15.642463Z","iopub.execute_input":"2025-10-23T17:05:15.642823Z","iopub.status.idle":"2025-10-23T17:05:21.487611Z","shell.execute_reply.started":"2025-10-23T17:05:15.642799Z","shell.execute_reply":"2025-10-23T17:05:21.486588Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nparam_grid = {\n    'n_estimators': [100, 200, 300],\n    'max_depth': [None, 10, 20, 30],\n    'min_samples_split': [2, 5, 10]\n}\n\ngrid = GridSearchCV(\n    estimator=RandomForestClassifier(random_state=42),\n    param_grid=param_grid,\n    cv=3,\n    n_jobs=-1,\n    verbose=2\n)\n\ngrid.fit(X_train_enc, y_train)\n\nprint(\"أفضل معاملات:\", grid.best_params_)\nprint(\"أفضل دقة تحقق:\", grid.best_score_)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-23T17:06:29.893045Z","iopub.execute_input":"2025-10-23T17:06:29.893394Z","iopub.status.idle":"2025-10-23T20:09:07.50718Z","shell.execute_reply.started":"2025-10-23T17:06:29.893367Z","shell.execute_reply":"2025-10-23T20:09:07.504509Z"}},"outputs":[],"execution_count":null}]}