{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "da9c60cf-38f3-41dd-bb2b-111074b89e0c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "18843d5f-160a-45cf-9bb9-3a49288d9ac4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "12234f9c-a72c-473f-bf37-72d6af0368ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv('subject_information.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "fc7ba166-b883-43d6-95e4-07b0c183fd5f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dataset shape: (60, 5)\n"
     ]
    }
   ],
   "source": [
    "print(f\"Dataset shape: {df.shape}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a911e95a-75e3-4534-8919-bf0e6ba084ce",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "First 5 rows:\n",
      "     Label  Age Sex   CKD  CKD_Stage\n",
      "0  CKD_01   52   M  True          2\n",
      "1  CKD_02   55   M  True          3\n",
      "2  CKD_03   48   F  True          5\n",
      "3  CKD_04   66   M  True          4\n",
      "4  CKD_05   50   M  True          5 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(\"First 5 rows:\\n\", df.head(), \"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "f31ea790-2647-46b9-b378-45ef1a0b0c82",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 60 entries, 0 to 59\n",
      "Data columns (total 5 columns):\n",
      " #   Column     Non-Null Count  Dtype \n",
      "---  ------     --------------  ----- \n",
      " 0   Label      60 non-null     object\n",
      " 1   Age        60 non-null     int64 \n",
      " 2   Sex        60 non-null     object\n",
      " 3   CKD        60 non-null     bool  \n",
      " 4   CKD_Stage  60 non-null     int64 \n",
      "dtypes: bool(1), int64(2), object(2)\n",
      "memory usage: 2.1+ KB\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "print(df.info())  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "cb3cf5da-0bdc-4b32-9378-fb4c056adc69",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "No missing values found in the dataset.\n"
     ]
    }
   ],
   "source": [
    "if df.isnull().values.any():\n",
    "    print(\"Handling missing values...\")\n",
    "    numeric_cols = df.select_dtypes(include=[np.number]).columns\n",
    "    # Impute numeric columns with median\n",
    "    df[numeric_cols] = df[numeric_cols].fillna(df[numeric_cols].median())\n",
    "    # Drop any remaining rows with missing values\n",
    "    df = df.dropna()\n",
    "    print(\"Missing values imputed or dropped.\")\n",
    "else:\n",
    "    print(\"No missing values found in the dataset.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "7e535883-4c43-4a9d-8699-12932e417f98",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "After encoding, first 5 rows:\n",
      "    Age  Sex  CKD  CKD_Stage\n",
      "0   52    1    1          2\n",
      "1   55    1    1          3\n",
      "2   48    0    1          5\n",
      "3   66    1    1          4\n",
      "4   50    1    1          5 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "df_processed = df.drop('Label', axis=1).copy()\n",
    "df_processed['Sex'] = df_processed['Sex'].map({'M': 1, 'F': 0})\n",
    "df_processed['CKD'] = df_processed['CKD'].astype(int)\n",
    "\n",
    "# Separate features and target variable\n",
    "X = df_processed.drop('CKD', axis=1)\n",
    "y = df_processed['CKD']\n",
    "\n",
    "print(\"After encoding, first 5 rows:\\n\", df_processed.head(), \"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "75ecb38b-1690-48c9-bed9-0dfb8845e174",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set size: 48 samples; Test set size: 12 samples.\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "# Split into training and test sets (80% train, 20% test)\n",
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "    X, y, test_size=0.2, stratify=y, random_state=42\n",
    ")\n",
    "print(f\"Training set size: {X_train.shape[0]} samples; Test set size: {X_test.shape[0]} samples.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "e4a44c56-e369-46cf-a43d-eb384b012ed5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Features scaled (Age and CKD_Stage).\n"
     ]
    }
   ],
   "source": [
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "# Initialize scaler and fit on training set's numeric features\n",
    "scaler = StandardScaler()\n",
    "X_train_scaled = X_train.copy()\n",
    "X_test_scaled = X_test.copy()\n",
    "\n",
    "# Only scale Age and CKD_Stage (Sex is binary 0/1 and doesn't need scaling)\n",
    "X_train_scaled[['Age', 'CKD_Stage']] = scaler.fit_transform(X_train_scaled[['Age', 'CKD_Stage']])\n",
    "X_test_scaled[['Age', 'CKD_Stage']] = scaler.transform(X_test_scaled[['Age', 'CKD_Stage']])\n",
    "print(\"Features scaled (Age and CKD_Stage).\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "4a92c6a6-9e3a-4261-b874-5add670329e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training Logistic Regression with GridSearchCV...\n",
      "Best parameters for Logistic Regression: {'C': 10, 'dual': False, 'penalty': 'l2'}\n",
      "\n",
      "Training Random Forest with GridSearchCV...\n",
      "Best parameters for Random Forest: {'criterion': 'gini', 'max_depth': None, 'n_estimators': 50}\n",
      "\n",
      "Training SVM with GridSearchCV...\n",
      "Best parameters for SVM: {'C': 10, 'kernel': 'linear'} \n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.svm import SVC\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "\n",
    "# Define models and hyperparameter grid\n",
    "log_model = LogisticRegression(solver='liblinear', max_iter=1000)\n",
    "log_param_grid = {\n",
    "    'C': [0.01, 0.1, 1, 10],\n",
    "    'penalty': ['l1', 'l2'],\n",
    "    'dual': [False]  # 'dual' must be False when using L1 with liblinear solver\n",
    "}\n",
    "rf_model = RandomForestClassifier(random_state=42)\n",
    "rf_param_grid = {\n",
    "    'n_estimators': [50, 100],\n",
    "    'max_depth': [None, 3, 5],\n",
    "    'criterion': ['gini', 'entropy']\n",
    "}\n",
    "svm_model = SVC()\n",
    "svm_param_grid = [\n",
    "    {'kernel': ['linear'], 'C': [0.1, 1, 10]},\n",
    "    {'kernel': ['rbf'], 'C': [0.1, 1, 10], 'gamma': [0.01, 0.1, 1]}\n",
    "]\n",
    "\n",
    "# Initialize GridSearch for each model\n",
    "log_grid = GridSearchCV(log_model, log_param_grid, cv=5)\n",
    "rf_grid = GridSearchCV(rf_model, rf_param_grid, cv=5)\n",
    "svm_grid = GridSearchCV(svm_model, svm_param_grid, cv=5)\n",
    "\n",
    "# Train (fit) each model on the training set\n",
    "print(\"Training Logistic Regression with GridSearchCV...\")\n",
    "log_grid.fit(X_train_scaled, y_train)\n",
    "print(\"Best parameters for Logistic Regression:\", log_grid.best_params_)\n",
    "\n",
    "print(\"\\nTraining Random Forest with GridSearchCV...\")\n",
    "rf_grid.fit(X_train_scaled, y_train)\n",
    "print(\"Best parameters for Random Forest:\", rf_grid.best_params_)\n",
    "\n",
    "print(\"\\nTraining SVM with GridSearchCV...\")\n",
    "svm_grid.fit(X_train_scaled, y_train)\n",
    "print(\"Best parameters for SVM:\", svm_grid.best_params_, \"\\n\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "518c8449-9702-45cd-bc32-a4af2eaa6ca6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Performance with All Features:\n",
      "                        Accuracy  Precision  Recall  F1-score\n",
      "Model                                                        \n",
      "Logistic Regression          1.0        1.0     1.0       1.0\n",
      "Random Forest                1.0        1.0     1.0       1.0\n",
      "Support Vector Machine       1.0        1.0     1.0       1.0 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\n",
    "\n",
    "# Best models from grid search\n",
    "best_log = log_grid.best_estimator_\n",
    "best_rf = rf_grid.best_estimator_\n",
    "best_svm = svm_grid.best_estimator_\n",
    "\n",
    "# Predictions on test data\n",
    "y_pred_log = best_log.predict(X_test_scaled)\n",
    "y_pred_rf = best_rf.predict(X_test_scaled)\n",
    "y_pred_svm = best_svm.predict(X_test_scaled)\n",
    "\n",
    "# Calculate metrics\n",
    "metrics = {\n",
    "    'Model': ['Logistic Regression', 'Random Forest', 'Support Vector Machine'],\n",
    "    'Accuracy': [\n",
    "        accuracy_score(y_test, y_pred_log),\n",
    "        accuracy_score(y_test, y_pred_rf),\n",
    "        accuracy_score(y_test, y_pred_svm)\n",
    "    ],\n",
    "    'Precision': [\n",
    "        precision_score(y_test, y_pred_log),\n",
    "        precision_score(y_test, y_pred_rf),\n",
    "        precision_score(y_test, y_pred_svm)\n",
    "    ],\n",
    "    'Recall': [\n",
    "        recall_score(y_test, y_pred_log),\n",
    "        recall_score(y_test, y_pred_rf),\n",
    "        recall_score(y_test, y_pred_svm)\n",
    "    ],\n",
    "    'F1-score': [\n",
    "        f1_score(y_test, y_pred_log),\n",
    "        f1_score(y_test, y_pred_rf),\n",
    "        f1_score(y_test, y_pred_svm)\n",
    "    ]\n",
    "}\n",
    "results_all = pd.DataFrame(metrics).set_index('Model')\n",
    "print(\"Model Performance with All Features:\")\n",
    "print(results_all.round(3), \"\\n\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "21d3dcb3-af5f-42c2-b09a-daf86f50bd28",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SelectKBest selected features (k=2): ['Age', 'CKD_Stage']\n"
     ]
    }
   ],
   "source": [
    "from sklearn.feature_selection import SelectKBest, chi2, RFE\n",
    "\n",
    "# SelectKBest with chi-squared to select 2 best features\n",
    "selector = SelectKBest(score_func=chi2, k=2)\n",
    "selector.fit(X_train, y_train)\n",
    "kbest_features = X_train.columns[selector.get_support()]\n",
    "print(\"SelectKBest selected features (k=2):\", list(kbest_features))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "60a868d1-5b78-4f6c-810e-858b190cd371",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RFE selected features (n=2): ['Age', 'CKD_Stage'] \n",
      "\n"
     ]
    }
   ],
   "source": [
    "rfe_estimator = LogisticRegression(solver='liblinear', penalty='l2', C=1)\n",
    "rfe = RFE(estimator=rfe_estimator, n_features_to_select=2)\n",
    "rfe.fit(X_train_scaled, y_train)\n",
    "rfe_features = X_train.columns[rfe.get_support()]\n",
    "print(\"RFE selected features (n=2):\", list(rfe_features), \"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "c76758c1-9bed-441d-a34c-98b5aaa27b3b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Performance with SelectKBest Features:\n",
      "                        Accuracy  Precision  Recall  F1-score\n",
      "Model                                                        \n",
      "Logistic Regression          1.0        1.0     1.0       1.0\n",
      "Random Forest                1.0        1.0     1.0       1.0\n",
      "Support Vector Machine       1.0        1.0     1.0       1.0 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "X_train_kbest = X_train_scaled[kbest_features]\n",
    "X_test_kbest = X_test_scaled[kbest_features]\n",
    "\n",
    "# Retrain models with selected features\n",
    "log_grid_k = GridSearchCV(log_model, log_param_grid, cv=5)\n",
    "rf_grid_k = GridSearchCV(rf_model, rf_param_grid, cv=5)\n",
    "svm_grid_k = GridSearchCV(svm_model, svm_param_grid, cv=5)\n",
    "\n",
    "log_grid_k.fit(X_train_kbest, y_train)\n",
    "rf_grid_k.fit(X_train_kbest, y_train)\n",
    "svm_grid_k.fit(X_train_kbest, y_train)\n",
    "\n",
    "# Best models\n",
    "best_log_k = log_grid_k.best_estimator_\n",
    "best_rf_k = rf_grid_k.best_estimator_\n",
    "best_svm_k = svm_grid_k.best_estimator_\n",
    "\n",
    "# Test set predictions and metrics\n",
    "y_pred_log_k = best_log_k.predict(X_test_kbest)\n",
    "y_pred_rf_k = best_rf_k.predict(X_test_kbest)\n",
    "y_pred_svm_k = best_svm_k.predict(X_test_kbest)\n",
    "\n",
    "results_kbest = pd.DataFrame({\n",
    "    'Model': ['Logistic Regression', 'Random Forest', 'Support Vector Machine'],\n",
    "    'Accuracy': [\n",
    "        accuracy_score(y_test, y_pred_log_k),\n",
    "        accuracy_score(y_test, y_pred_rf_k),\n",
    "        accuracy_score(y_test, y_pred_svm_k)\n",
    "    ],\n",
    "    'Precision': [\n",
    "        precision_score(y_test, y_pred_log_k),\n",
    "        precision_score(y_test, y_pred_rf_k),\n",
    "        precision_score(y_test, y_pred_svm_k)\n",
    "    ],\n",
    "    'Recall': [\n",
    "        recall_score(y_test, y_pred_log_k),\n",
    "        recall_score(y_test, y_pred_rf_k),\n",
    "        recall_score(y_test, y_pred_svm_k)\n",
    "    ],\n",
    "    'F1-score': [\n",
    "        f1_score(y_test, y_pred_log_k),\n",
    "        f1_score(y_test, y_pred_rf_k),\n",
    "        f1_score(y_test, y_pred_svm_k)\n",
    "    ]\n",
    "}).set_index('Model')\n",
    "print(\"Model Performance with SelectKBest Features:\")\n",
    "print(results_kbest.round(3), \"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "32dc8e1e-3b37-4482-8dba-e1bbe5384a9a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Performance with RFE Features:\n",
      "                        Accuracy  Precision  Recall  F1-score\n",
      "Model                                                        \n",
      "Logistic Regression          1.0        1.0     1.0       1.0\n",
      "Random Forest                1.0        1.0     1.0       1.0\n",
      "Support Vector Machine       1.0        1.0     1.0       1.0 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "X_train_rfe = X_train_scaled[rfe_features]\n",
    "X_test_rfe = X_test_scaled[rfe_features]\n",
    "\n",
    "# Retrain models with RFE selected features\n",
    "log_grid_r = GridSearchCV(log_model, log_param_grid, cv=5)\n",
    "rf_grid_r = GridSearchCV(rf_model, rf_param_grid, cv=5)\n",
    "svm_grid_r = GridSearchCV(svm_model, svm_param_grid, cv=5)\n",
    "\n",
    "log_grid_r.fit(X_train_rfe, y_train)\n",
    "rf_grid_r.fit(X_train_rfe, y_train)\n",
    "svm_grid_r.fit(X_train_rfe, y_train)\n",
    "\n",
    "best_log_r = log_grid_r.best_estimator_\n",
    "best_rf_r = rf_grid_r.best_estimator_\n",
    "best_svm_r = svm_grid_r.best_estimator_\n",
    "\n",
    "y_pred_log_r = best_log_r.predict(X_test_rfe)\n",
    "y_pred_rf_r = best_rf_r.predict(X_test_rfe)\n",
    "y_pred_svm_r = best_svm_r.predict(X_test_rfe)\n",
    "\n",
    "results_rfe = pd.DataFrame({\n",
    "    'Model': ['Logistic Regression', 'Random Forest', 'Support Vector Machine'],\n",
    "    'Accuracy': [\n",
    "        accuracy_score(y_test, y_pred_log_r),\n",
    "        accuracy_score(y_test, y_pred_rf_r),\n",
    "        accuracy_score(y_test, y_pred_svm_r)\n",
    "    ],\n",
    "    'Precision': [\n",
    "        precision_score(y_test, y_pred_log_r),\n",
    "        precision_score(y_test, y_pred_rf_r),\n",
    "        precision_score(y_test, y_pred_svm_r)\n",
    "    ],\n",
    "    'Recall': [\n",
    "        recall_score(y_test, y_pred_log_r),\n",
    "        recall_score(y_test, y_pred_rf_r),\n",
    "        recall_score(y_test, y_pred_svm_r)\n",
    "    ],\n",
    "    'F1-score': [\n",
    "        f1_score(y_test, y_pred_log_r),\n",
    "        f1_score(y_test, y_pred_rf_r),\n",
    "        f1_score(y_test, y_pred_svm_r)\n",
    "    ]\n",
    "}).set_index('Model')\n",
    "print(\"Model Performance with RFE Features:\")\n",
    "print(results_rfe.round(3), \"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "11717c3d-8aeb-4f85-acdd-35da4b4e8b40",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processed dataset saved as 'subject_information_processed.csv'.\n"
     ]
    }
   ],
   "source": [
    "df_processed.to_csv('subject_information_processed.csv', index=False)\n",
    "print(\"Processed dataset saved as 'subject_information_processed.csv'.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8e70da6b-f975-4214-b564-c9f5e369ab88",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
