3595 lines
176 KiB
Plaintext
3595 lines
176 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "84b6e27e-4bda-4d38-8689-ec7fc0da1848",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Define segment and predict sales associated"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "ec059482-45d3-4ae6-99bc-9b4ced115db3",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Importations of packages "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"id": "9771bf29-d08e-4674-8c23-9a2672fbef8f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"from pandas import DataFrame\n",
|
||
"import numpy as np\n",
|
||
"import os\n",
|
||
"import s3fs\n",
|
||
"import re\n",
|
||
"from sklearn.linear_model import LogisticRegression\n",
|
||
"from sklearn.ensemble import RandomForestClassifier\n",
|
||
"from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, recall_score\n",
|
||
"from sklearn.utils import class_weight\n",
|
||
"from sklearn.neighbors import KNeighborsClassifier\n",
|
||
"from sklearn.pipeline import Pipeline\n",
|
||
"from sklearn.compose import ColumnTransformer\n",
|
||
"from sklearn.preprocessing import OneHotEncoder\n",
|
||
"from sklearn.impute import SimpleImputer\n",
|
||
"from sklearn.model_selection import GridSearchCV\n",
|
||
"from sklearn.preprocessing import StandardScaler, MaxAbsScaler, MinMaxScaler\n",
|
||
"from sklearn.metrics import make_scorer, f1_score, balanced_accuracy_score\n",
|
||
"import seaborn as sns\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"from sklearn.metrics import roc_curve, auc, precision_recall_curve, average_precision_score\n",
|
||
"from sklearn.exceptions import ConvergenceWarning, DataConversionWarning\n",
|
||
"from sklearn.naive_bayes import GaussianNB\n",
|
||
"from scipy.optimize import fsolve\n",
|
||
"import io\n",
|
||
"\n",
|
||
"import pickle\n",
|
||
"import warnings"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "048fcd7c-800a-4a6b-b725-faf8410f924a",
|
||
"metadata": {},
|
||
"source": [
|
||
"## load databases"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"id": "539ccbdf-f29f-4f04-99c1-8c88d0efe514",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Create filesystem object\n",
|
||
"S3_ENDPOINT_URL = \"https://\" + os.environ[\"AWS_S3_ENDPOINT\"]\n",
|
||
"fs = s3fs.S3FileSystem(client_kwargs={'endpoint_url': S3_ENDPOINT_URL})"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 31,
|
||
"id": "d6017ed0-6233-4888-85a7-05dec50a255b",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"type_of_activity = \"musique\""
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"id": "0c3a6ddc-9345-4a42-b6bf-a20a95de3028",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def load_train_test(type_of_activity):\n",
|
||
" BUCKET = f\"projet-bdc2324-team1/Generalization/{type_of_activity}\"\n",
|
||
" File_path_train = BUCKET + \"/Train_set.csv\"\n",
|
||
" File_path_test = BUCKET + \"/Test_set.csv\"\n",
|
||
" \n",
|
||
" with fs.open( File_path_train, mode=\"rb\") as file_in:\n",
|
||
" dataset_train = pd.read_csv(file_in, sep=\",\")\n",
|
||
" # dataset_train['y_has_purchased'] = dataset_train['y_has_purchased'].fillna(0)\n",
|
||
"\n",
|
||
" with fs.open(File_path_test, mode=\"rb\") as file_in:\n",
|
||
" dataset_test = pd.read_csv(file_in, sep=\",\")\n",
|
||
" # dataset_test['y_has_purchased'] = dataset_test['y_has_purchased'].fillna(0)\n",
|
||
" \n",
|
||
" return dataset_train, dataset_test"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 32,
|
||
"id": "2831d546-b365-498b-8248-c618bd9c3057",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1080/2350085345.py:7: DtypeWarning: Columns (38) have mixed types. Specify dtype option on import or set low_memory=False.\n",
|
||
" dataset_train = pd.read_csv(file_in, sep=\",\")\n",
|
||
"/tmp/ipykernel_1080/2350085345.py:11: DtypeWarning: Columns (38) have mixed types. Specify dtype option on import or set low_memory=False.\n",
|
||
" dataset_test = pd.read_csv(file_in, sep=\",\")\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"customer_id 0\n",
|
||
"nb_tickets 0\n",
|
||
"nb_purchases 0\n",
|
||
"total_amount 0\n",
|
||
"nb_suppliers 0\n",
|
||
"vente_internet_max 0\n",
|
||
"purchase_date_min 0\n",
|
||
"purchase_date_max 0\n",
|
||
"time_between_purchase 0\n",
|
||
"nb_tickets_internet 0\n",
|
||
"street_id 0\n",
|
||
"structure_id 327067\n",
|
||
"mcp_contact_id 135224\n",
|
||
"fidelity 0\n",
|
||
"tenant_id 0\n",
|
||
"is_partner 0\n",
|
||
"deleted_at 354365\n",
|
||
"gender 0\n",
|
||
"is_email_true 0\n",
|
||
"opt_in 0\n",
|
||
"last_buying_date 119201\n",
|
||
"max_price 119201\n",
|
||
"ticket_sum 0\n",
|
||
"average_price 115193\n",
|
||
"average_purchase_delay 119203\n",
|
||
"average_price_basket 119203\n",
|
||
"average_ticket_basket 119203\n",
|
||
"total_price 4008\n",
|
||
"purchase_count 0\n",
|
||
"first_buying_date 119201\n",
|
||
"country 56856\n",
|
||
"gender_label 0\n",
|
||
"gender_female 0\n",
|
||
"gender_male 0\n",
|
||
"gender_other 0\n",
|
||
"country_fr 56856\n",
|
||
"nb_campaigns 0\n",
|
||
"nb_campaigns_opened 0\n",
|
||
"time_to_open 224310\n",
|
||
"y_has_purchased 0\n",
|
||
"dtype: int64"
|
||
]
|
||
},
|
||
"execution_count": 32,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"dataset_train, dataset_test = load_train_test(type_of_activity)\n",
|
||
"dataset_train.isna().sum()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"id": "b8827f7b-b304-4f51-9814-c7a98ed88cf0",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def features_target_split(dataset_train, dataset_test):\n",
|
||
" \n",
|
||
" features_l = ['nb_tickets', 'nb_purchases', 'total_amount', 'nb_suppliers', 'vente_internet_max', 'purchase_date_min', 'purchase_date_max', \n",
|
||
" 'time_between_purchase', 'nb_tickets_internet', 'fidelity', 'is_email_true', 'opt_in', #'is_partner',\n",
|
||
" 'gender_female', 'gender_male', 'gender_other', 'nb_campaigns', 'nb_campaigns_opened']\n",
|
||
"\n",
|
||
" # we suppress fidelity, time between purchase, and gender other (colinearity issue)\n",
|
||
" \"\"\"\n",
|
||
" features_l = ['nb_tickets', 'nb_purchases', 'total_amount', 'nb_suppliers', 'vente_internet_max', \n",
|
||
" 'purchase_date_min', 'purchase_date_max', 'nb_tickets_internet', 'is_email_true', \n",
|
||
" 'opt_in', 'gender_female', 'gender_male', 'nb_campaigns', 'nb_campaigns_opened']\n",
|
||
" \"\"\"\n",
|
||
" \n",
|
||
" X_train = dataset_train[features_l]\n",
|
||
" y_train = dataset_train[['y_has_purchased']]\n",
|
||
"\n",
|
||
" X_test = dataset_test[features_l]\n",
|
||
" y_test = dataset_test[['y_has_purchased']]\n",
|
||
" return X_train, X_test, y_train, y_test"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 33,
|
||
"id": "c18195fc-ed40-4e39-a59e-c9ecc5a8e6c3",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Shape train : (354365, 17)\n",
|
||
"Shape test : (151874, 17)\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"X_train, X_test, y_train, y_test = features_target_split(dataset_train, dataset_test)\n",
|
||
"print(\"Shape train : \", X_train.shape)\n",
|
||
"print(\"Shape test : \", X_test.shape)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "74eda066-5e01-43aa-b0cf-cc6d9bbf770e",
|
||
"metadata": {},
|
||
"source": [
|
||
"## get results from the logit cross validated model"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"id": "7c81390e-598c-4f02-bd56-dd03b00dcb33",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>nb_tickets</th>\n",
|
||
" <th>nb_purchases</th>\n",
|
||
" <th>total_amount</th>\n",
|
||
" <th>nb_suppliers</th>\n",
|
||
" <th>vente_internet_max</th>\n",
|
||
" <th>purchase_date_min</th>\n",
|
||
" <th>purchase_date_max</th>\n",
|
||
" <th>time_between_purchase</th>\n",
|
||
" <th>nb_tickets_internet</th>\n",
|
||
" <th>fidelity</th>\n",
|
||
" <th>is_email_true</th>\n",
|
||
" <th>opt_in</th>\n",
|
||
" <th>gender_female</th>\n",
|
||
" <th>gender_male</th>\n",
|
||
" <th>gender_other</th>\n",
|
||
" <th>nb_campaigns</th>\n",
|
||
" <th>nb_campaigns_opened</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>22.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>307.203553</td>\n",
|
||
" <td>307.203553</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>False</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>269.0</td>\n",
|
||
" <td>8.0</td>\n",
|
||
" <td>50.0</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>378.208090</td>\n",
|
||
" <td>39.389595</td>\n",
|
||
" <td>338.818495</td>\n",
|
||
" <td>66.0</td>\n",
|
||
" <td>10</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>65.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>4</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>...</th>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>186115</th>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>96.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>117.364572</td>\n",
|
||
" <td>117.364572</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>False</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>186116</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>46.0</td>\n",
|
||
" <td>13.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>186117</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>84.0</td>\n",
|
||
" <td>24.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>186118</th>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>165.538391</td>\n",
|
||
" <td>165.538391</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>False</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>186119</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>True</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>47.0</td>\n",
|
||
" <td>21.0</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"<p>186120 rows × 17 columns</p>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" nb_tickets nb_purchases total_amount nb_suppliers \\\n",
|
||
"0 2.0 1.0 22.0 1.0 \n",
|
||
"1 269.0 8.0 50.0 2.0 \n",
|
||
"2 0.0 0.0 0.0 0.0 \n",
|
||
"3 0.0 0.0 0.0 0.0 \n",
|
||
"4 0.0 0.0 0.0 0.0 \n",
|
||
"... ... ... ... ... \n",
|
||
"186115 4.0 1.0 96.0 1.0 \n",
|
||
"186116 0.0 0.0 0.0 0.0 \n",
|
||
"186117 0.0 0.0 0.0 0.0 \n",
|
||
"186118 1.0 1.0 0.0 1.0 \n",
|
||
"186119 0.0 0.0 0.0 0.0 \n",
|
||
"\n",
|
||
" vente_internet_max purchase_date_min purchase_date_max \\\n",
|
||
"0 1.0 307.203553 307.203553 \n",
|
||
"1 1.0 378.208090 39.389595 \n",
|
||
"2 0.0 550.000000 550.000000 \n",
|
||
"3 0.0 550.000000 550.000000 \n",
|
||
"4 0.0 550.000000 550.000000 \n",
|
||
"... ... ... ... \n",
|
||
"186115 0.0 117.364572 117.364572 \n",
|
||
"186116 0.0 550.000000 550.000000 \n",
|
||
"186117 0.0 550.000000 550.000000 \n",
|
||
"186118 0.0 165.538391 165.538391 \n",
|
||
"186119 0.0 550.000000 550.000000 \n",
|
||
"\n",
|
||
" time_between_purchase nb_tickets_internet fidelity is_email_true \\\n",
|
||
"0 0.000000 2.0 1 True \n",
|
||
"1 338.818495 66.0 10 True \n",
|
||
"2 -1.000000 0.0 0 True \n",
|
||
"3 -1.000000 0.0 0 True \n",
|
||
"4 -1.000000 0.0 0 True \n",
|
||
"... ... ... ... ... \n",
|
||
"186115 0.000000 0.0 1 True \n",
|
||
"186116 -1.000000 0.0 0 True \n",
|
||
"186117 -1.000000 0.0 0 True \n",
|
||
"186118 0.000000 0.0 1 True \n",
|
||
"186119 -1.000000 0.0 0 True \n",
|
||
"\n",
|
||
" opt_in gender_female gender_male gender_other nb_campaigns \\\n",
|
||
"0 False 0 0 1 0.0 \n",
|
||
"1 True 0 0 1 65.0 \n",
|
||
"2 True 0 1 0 4.0 \n",
|
||
"3 True 1 0 0 2.0 \n",
|
||
"4 True 0 0 1 4.0 \n",
|
||
"... ... ... ... ... ... \n",
|
||
"186115 False 1 0 0 1.0 \n",
|
||
"186116 True 0 1 0 46.0 \n",
|
||
"186117 True 0 1 0 84.0 \n",
|
||
"186118 False 1 0 0 1.0 \n",
|
||
"186119 True 0 0 1 47.0 \n",
|
||
"\n",
|
||
" nb_campaigns_opened \n",
|
||
"0 0.0 \n",
|
||
"1 1.0 \n",
|
||
"2 2.0 \n",
|
||
"3 0.0 \n",
|
||
"4 0.0 \n",
|
||
"... ... \n",
|
||
"186115 0.0 \n",
|
||
"186116 13.0 \n",
|
||
"186117 24.0 \n",
|
||
"186118 0.0 \n",
|
||
"186119 21.0 \n",
|
||
"\n",
|
||
"[186120 rows x 17 columns]"
|
||
]
|
||
},
|
||
"execution_count": 8,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 9,
|
||
"id": "c708f439-bb75-4688-bf4f-4c04e13deaae",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def load_model(type_of_activity, model):\n",
|
||
" BUCKET = f\"projet-bdc2324-team1/Output_model/{type_of_activity}/{model}/\"\n",
|
||
" filename = model + '.pkl'\n",
|
||
" file_path = BUCKET + filename\n",
|
||
" with fs.open(file_path, mode=\"rb\") as f:\n",
|
||
" model_bytes = f.read()\n",
|
||
"\n",
|
||
" model = pickle.loads(model_bytes)\n",
|
||
" return model"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 34,
|
||
"id": "5261a803-05b8-41a0-968c-dc7bde48ddd3",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<style>#sk-container-id-2 {\n",
|
||
" /* Definition of color scheme common for light and dark mode */\n",
|
||
" --sklearn-color-text: black;\n",
|
||
" --sklearn-color-line: gray;\n",
|
||
" /* Definition of color scheme for unfitted estimators */\n",
|
||
" --sklearn-color-unfitted-level-0: #fff5e6;\n",
|
||
" --sklearn-color-unfitted-level-1: #f6e4d2;\n",
|
||
" --sklearn-color-unfitted-level-2: #ffe0b3;\n",
|
||
" --sklearn-color-unfitted-level-3: chocolate;\n",
|
||
" /* Definition of color scheme for fitted estimators */\n",
|
||
" --sklearn-color-fitted-level-0: #f0f8ff;\n",
|
||
" --sklearn-color-fitted-level-1: #d4ebff;\n",
|
||
" --sklearn-color-fitted-level-2: #b3dbfd;\n",
|
||
" --sklearn-color-fitted-level-3: cornflowerblue;\n",
|
||
"\n",
|
||
" /* Specific color for light theme */\n",
|
||
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
|
||
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
|
||
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
|
||
" --sklearn-color-icon: #696969;\n",
|
||
"\n",
|
||
" @media (prefers-color-scheme: dark) {\n",
|
||
" /* Redefinition of color scheme for dark theme */\n",
|
||
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
|
||
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
|
||
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
|
||
" --sklearn-color-icon: #878787;\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 {\n",
|
||
" color: var(--sklearn-color-text);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 pre {\n",
|
||
" padding: 0;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 input.sk-hidden--visually {\n",
|
||
" border: 0;\n",
|
||
" clip: rect(1px 1px 1px 1px);\n",
|
||
" clip: rect(1px, 1px, 1px, 1px);\n",
|
||
" height: 1px;\n",
|
||
" margin: -1px;\n",
|
||
" overflow: hidden;\n",
|
||
" padding: 0;\n",
|
||
" position: absolute;\n",
|
||
" width: 1px;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-dashed-wrapped {\n",
|
||
" border: 1px dashed var(--sklearn-color-line);\n",
|
||
" margin: 0 0.4em 0.5em 0.4em;\n",
|
||
" box-sizing: border-box;\n",
|
||
" padding-bottom: 0.4em;\n",
|
||
" background-color: var(--sklearn-color-background);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-container {\n",
|
||
" /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
|
||
" but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
|
||
" so we also need the `!important` here to be able to override the\n",
|
||
" default hidden behavior on the sphinx rendered scikit-learn.org.\n",
|
||
" See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
|
||
" display: inline-block !important;\n",
|
||
" position: relative;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-text-repr-fallback {\n",
|
||
" display: none;\n",
|
||
"}\n",
|
||
"\n",
|
||
"div.sk-parallel-item,\n",
|
||
"div.sk-serial,\n",
|
||
"div.sk-item {\n",
|
||
" /* draw centered vertical line to link estimators */\n",
|
||
" background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
|
||
" background-size: 2px 100%;\n",
|
||
" background-repeat: no-repeat;\n",
|
||
" background-position: center center;\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Parallel-specific style estimator block */\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-parallel-item::after {\n",
|
||
" content: \"\";\n",
|
||
" width: 100%;\n",
|
||
" border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
|
||
" flex-grow: 1;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-parallel {\n",
|
||
" display: flex;\n",
|
||
" align-items: stretch;\n",
|
||
" justify-content: center;\n",
|
||
" background-color: var(--sklearn-color-background);\n",
|
||
" position: relative;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-parallel-item {\n",
|
||
" display: flex;\n",
|
||
" flex-direction: column;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-parallel-item:first-child::after {\n",
|
||
" align-self: flex-end;\n",
|
||
" width: 50%;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-parallel-item:last-child::after {\n",
|
||
" align-self: flex-start;\n",
|
||
" width: 50%;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-parallel-item:only-child::after {\n",
|
||
" width: 0;\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Serial-specific style estimator block */\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-serial {\n",
|
||
" display: flex;\n",
|
||
" flex-direction: column;\n",
|
||
" align-items: center;\n",
|
||
" background-color: var(--sklearn-color-background);\n",
|
||
" padding-right: 1em;\n",
|
||
" padding-left: 1em;\n",
|
||
"}\n",
|
||
"\n",
|
||
"\n",
|
||
"/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
|
||
"clickable and can be expanded/collapsed.\n",
|
||
"- Pipeline and ColumnTransformer use this feature and define the default style\n",
|
||
"- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
|
||
"*/\n",
|
||
"\n",
|
||
"/* Pipeline and ColumnTransformer style (default) */\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-toggleable {\n",
|
||
" /* Default theme specific background. It is overwritten whether we have a\n",
|
||
" specific estimator or a Pipeline/ColumnTransformer */\n",
|
||
" background-color: var(--sklearn-color-background);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Toggleable label */\n",
|
||
"#sk-container-id-2 label.sk-toggleable__label {\n",
|
||
" cursor: pointer;\n",
|
||
" display: block;\n",
|
||
" width: 100%;\n",
|
||
" margin-bottom: 0;\n",
|
||
" padding: 0.5em;\n",
|
||
" box-sizing: border-box;\n",
|
||
" text-align: center;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 label.sk-toggleable__label-arrow:before {\n",
|
||
" /* Arrow on the left of the label */\n",
|
||
" content: \"▸\";\n",
|
||
" float: left;\n",
|
||
" margin-right: 0.25em;\n",
|
||
" color: var(--sklearn-color-icon);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {\n",
|
||
" color: var(--sklearn-color-text);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Toggleable content - dropdown */\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-toggleable__content {\n",
|
||
" max-height: 0;\n",
|
||
" max-width: 0;\n",
|
||
" overflow: hidden;\n",
|
||
" text-align: left;\n",
|
||
" /* unfitted */\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-toggleable__content.fitted {\n",
|
||
" /* fitted */\n",
|
||
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-toggleable__content pre {\n",
|
||
" margin: 0.2em;\n",
|
||
" border-radius: 0.25em;\n",
|
||
" color: var(--sklearn-color-text);\n",
|
||
" /* unfitted */\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-toggleable__content.fitted pre {\n",
|
||
" /* unfitted */\n",
|
||
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
|
||
" /* Expand drop-down */\n",
|
||
" max-height: 200px;\n",
|
||
" max-width: 100%;\n",
|
||
" overflow: auto;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
|
||
" content: \"▾\";\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Pipeline/ColumnTransformer-specific style */\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
||
" color: var(--sklearn-color-text);\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
||
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Estimator-specific style */\n",
|
||
"\n",
|
||
"/* Colorize estimator box */\n",
|
||
"#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
||
" /* unfitted */\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
||
" /* fitted */\n",
|
||
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-label label.sk-toggleable__label,\n",
|
||
"#sk-container-id-2 div.sk-label label {\n",
|
||
" /* The background is the default theme color */\n",
|
||
" color: var(--sklearn-color-text-on-default-background);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* On hover, darken the color of the background */\n",
|
||
"#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {\n",
|
||
" color: var(--sklearn-color-text);\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Label box, darken color on hover, fitted */\n",
|
||
"#sk-container-id-2 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
|
||
" color: var(--sklearn-color-text);\n",
|
||
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Estimator label */\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-label label {\n",
|
||
" font-family: monospace;\n",
|
||
" font-weight: bold;\n",
|
||
" display: inline-block;\n",
|
||
" line-height: 1.2em;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-label-container {\n",
|
||
" text-align: center;\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Estimator-specific */\n",
|
||
"#sk-container-id-2 div.sk-estimator {\n",
|
||
" font-family: monospace;\n",
|
||
" border: 1px dotted var(--sklearn-color-border-box);\n",
|
||
" border-radius: 0.25em;\n",
|
||
" box-sizing: border-box;\n",
|
||
" margin-bottom: 0.5em;\n",
|
||
" /* unfitted */\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-estimator.fitted {\n",
|
||
" /* fitted */\n",
|
||
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* on hover */\n",
|
||
"#sk-container-id-2 div.sk-estimator:hover {\n",
|
||
" /* unfitted */\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 div.sk-estimator.fitted:hover {\n",
|
||
" /* fitted */\n",
|
||
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
|
||
"\n",
|
||
"/* Common style for \"i\" and \"?\" */\n",
|
||
"\n",
|
||
".sk-estimator-doc-link,\n",
|
||
"a:link.sk-estimator-doc-link,\n",
|
||
"a:visited.sk-estimator-doc-link {\n",
|
||
" float: right;\n",
|
||
" font-size: smaller;\n",
|
||
" line-height: 1em;\n",
|
||
" font-family: monospace;\n",
|
||
" background-color: var(--sklearn-color-background);\n",
|
||
" border-radius: 1em;\n",
|
||
" height: 1em;\n",
|
||
" width: 1em;\n",
|
||
" text-decoration: none !important;\n",
|
||
" margin-left: 1ex;\n",
|
||
" /* unfitted */\n",
|
||
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
|
||
" color: var(--sklearn-color-unfitted-level-1);\n",
|
||
"}\n",
|
||
"\n",
|
||
".sk-estimator-doc-link.fitted,\n",
|
||
"a:link.sk-estimator-doc-link.fitted,\n",
|
||
"a:visited.sk-estimator-doc-link.fitted {\n",
|
||
" /* fitted */\n",
|
||
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
|
||
" color: var(--sklearn-color-fitted-level-1);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* On hover */\n",
|
||
"div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
|
||
".sk-estimator-doc-link:hover,\n",
|
||
"div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
|
||
".sk-estimator-doc-link:hover {\n",
|
||
" /* unfitted */\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-3);\n",
|
||
" color: var(--sklearn-color-background);\n",
|
||
" text-decoration: none;\n",
|
||
"}\n",
|
||
"\n",
|
||
"div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
|
||
".sk-estimator-doc-link.fitted:hover,\n",
|
||
"div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
|
||
".sk-estimator-doc-link.fitted:hover {\n",
|
||
" /* fitted */\n",
|
||
" background-color: var(--sklearn-color-fitted-level-3);\n",
|
||
" color: var(--sklearn-color-background);\n",
|
||
" text-decoration: none;\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Span, style for the box shown on hovering the info icon */\n",
|
||
".sk-estimator-doc-link span {\n",
|
||
" display: none;\n",
|
||
" z-index: 9999;\n",
|
||
" position: relative;\n",
|
||
" font-weight: normal;\n",
|
||
" right: .2ex;\n",
|
||
" padding: .5ex;\n",
|
||
" margin: .5ex;\n",
|
||
" width: min-content;\n",
|
||
" min-width: 20ex;\n",
|
||
" max-width: 50ex;\n",
|
||
" color: var(--sklearn-color-text);\n",
|
||
" box-shadow: 2pt 2pt 4pt #999;\n",
|
||
" /* unfitted */\n",
|
||
" background: var(--sklearn-color-unfitted-level-0);\n",
|
||
" border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
|
||
"}\n",
|
||
"\n",
|
||
".sk-estimator-doc-link.fitted span {\n",
|
||
" /* fitted */\n",
|
||
" background: var(--sklearn-color-fitted-level-0);\n",
|
||
" border: var(--sklearn-color-fitted-level-3);\n",
|
||
"}\n",
|
||
"\n",
|
||
".sk-estimator-doc-link:hover span {\n",
|
||
" display: block;\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* \"?\"-specific style due to the `<a>` HTML tag */\n",
|
||
"\n",
|
||
"#sk-container-id-2 a.estimator_doc_link {\n",
|
||
" float: right;\n",
|
||
" font-size: 1rem;\n",
|
||
" line-height: 1em;\n",
|
||
" font-family: monospace;\n",
|
||
" background-color: var(--sklearn-color-background);\n",
|
||
" border-radius: 1rem;\n",
|
||
" height: 1rem;\n",
|
||
" width: 1rem;\n",
|
||
" text-decoration: none;\n",
|
||
" /* unfitted */\n",
|
||
" color: var(--sklearn-color-unfitted-level-1);\n",
|
||
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 a.estimator_doc_link.fitted {\n",
|
||
" /* fitted */\n",
|
||
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
|
||
" color: var(--sklearn-color-fitted-level-1);\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* On hover */\n",
|
||
"#sk-container-id-2 a.estimator_doc_link:hover {\n",
|
||
" /* unfitted */\n",
|
||
" background-color: var(--sklearn-color-unfitted-level-3);\n",
|
||
" color: var(--sklearn-color-background);\n",
|
||
" text-decoration: none;\n",
|
||
"}\n",
|
||
"\n",
|
||
"#sk-container-id-2 a.estimator_doc_link.fitted:hover {\n",
|
||
" /* fitted */\n",
|
||
" background-color: var(--sklearn-color-fitted-level-3);\n",
|
||
"}\n",
|
||
"</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>GridSearchCV(cv=3, error_score='raise',\n",
|
||
" estimator=Pipeline(steps=[('preprocessor',\n",
|
||
" ColumnTransformer(transformers=[('num',\n",
|
||
" Pipeline(steps=[('scaler',\n",
|
||
" StandardScaler())]),\n",
|
||
" ['nb_tickets',\n",
|
||
" 'nb_purchases',\n",
|
||
" 'total_amount',\n",
|
||
" 'nb_suppliers',\n",
|
||
" 'vente_internet_max',\n",
|
||
" 'purchase_date_min',\n",
|
||
" 'purchase_date_max',\n",
|
||
" 'time_between_purchase',\n",
|
||
" 'nb_tickets_internet',\n",
|
||
" 'nb_campaigns',\n",
|
||
" 'nb_...\n",
|
||
" 1.562500e-02, 3.125000e-02, 6.250000e-02, 1.250000e-01,\n",
|
||
" 2.500000e-01, 5.000000e-01, 1.000000e+00, 2.000000e+00,\n",
|
||
" 4.000000e+00, 8.000000e+00, 1.600000e+01, 3.200000e+01,\n",
|
||
" 6.400000e+01]),\n",
|
||
" 'LogisticRegression_cv__class_weight': ['balanced',\n",
|
||
" {0.0: 0.5481283836040216,\n",
|
||
" 1.0: 5.694439980716696}],\n",
|
||
" 'LogisticRegression_cv__penalty': ['l1', 'l2']},\n",
|
||
" scoring=make_scorer(recall_score, response_method='predict'))</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-9\" type=\"checkbox\" ><label for=\"sk-estimator-id-9\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> GridSearchCV<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.model_selection.GridSearchCV.html\">?<span>Documentation for GridSearchCV</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>GridSearchCV(cv=3, error_score='raise',\n",
|
||
" estimator=Pipeline(steps=[('preprocessor',\n",
|
||
" ColumnTransformer(transformers=[('num',\n",
|
||
" Pipeline(steps=[('scaler',\n",
|
||
" StandardScaler())]),\n",
|
||
" ['nb_tickets',\n",
|
||
" 'nb_purchases',\n",
|
||
" 'total_amount',\n",
|
||
" 'nb_suppliers',\n",
|
||
" 'vente_internet_max',\n",
|
||
" 'purchase_date_min',\n",
|
||
" 'purchase_date_max',\n",
|
||
" 'time_between_purchase',\n",
|
||
" 'nb_tickets_internet',\n",
|
||
" 'nb_campaigns',\n",
|
||
" 'nb_...\n",
|
||
" 1.562500e-02, 3.125000e-02, 6.250000e-02, 1.250000e-01,\n",
|
||
" 2.500000e-01, 5.000000e-01, 1.000000e+00, 2.000000e+00,\n",
|
||
" 4.000000e+00, 8.000000e+00, 1.600000e+01, 3.200000e+01,\n",
|
||
" 6.400000e+01]),\n",
|
||
" 'LogisticRegression_cv__class_weight': ['balanced',\n",
|
||
" {0.0: 0.5481283836040216,\n",
|
||
" 1.0: 5.694439980716696}],\n",
|
||
" 'LogisticRegression_cv__penalty': ['l1', 'l2']},\n",
|
||
" scoring=make_scorer(recall_score, response_method='predict'))</pre></div> </div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-10\" type=\"checkbox\" ><label for=\"sk-estimator-id-10\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">estimator: Pipeline</label><div class=\"sk-toggleable__content fitted\"><pre>Pipeline(steps=[('preprocessor',\n",
|
||
" ColumnTransformer(transformers=[('num',\n",
|
||
" Pipeline(steps=[('scaler',\n",
|
||
" StandardScaler())]),\n",
|
||
" ['nb_tickets', 'nb_purchases',\n",
|
||
" 'total_amount',\n",
|
||
" 'nb_suppliers',\n",
|
||
" 'vente_internet_max',\n",
|
||
" 'purchase_date_min',\n",
|
||
" 'purchase_date_max',\n",
|
||
" 'time_between_purchase',\n",
|
||
" 'nb_tickets_internet',\n",
|
||
" 'nb_campaigns',\n",
|
||
" 'nb_campaigns_opened']),\n",
|
||
" ('cat',\n",
|
||
" Pipeline(steps=[('onehot',\n",
|
||
" OneHotEncoder(handle_unknown='ignore',\n",
|
||
" sparse_output=False))]),\n",
|
||
" ['opt_in', 'gender_male',\n",
|
||
" 'gender_female'])])),\n",
|
||
" ('LogisticRegression_cv',\n",
|
||
" LogisticRegression(max_iter=5000, solver='saga'))])</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-serial\"><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-11\" type=\"checkbox\" ><label for=\"sk-estimator-id-11\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> preprocessor: ColumnTransformer<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.compose.ColumnTransformer.html\">?<span>Documentation for preprocessor: ColumnTransformer</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>ColumnTransformer(transformers=[('num',\n",
|
||
" Pipeline(steps=[('scaler', StandardScaler())]),\n",
|
||
" ['nb_tickets', 'nb_purchases', 'total_amount',\n",
|
||
" 'nb_suppliers', 'vente_internet_max',\n",
|
||
" 'purchase_date_min', 'purchase_date_max',\n",
|
||
" 'time_between_purchase',\n",
|
||
" 'nb_tickets_internet', 'nb_campaigns',\n",
|
||
" 'nb_campaigns_opened']),\n",
|
||
" ('cat',\n",
|
||
" Pipeline(steps=[('onehot',\n",
|
||
" OneHotEncoder(handle_unknown='ignore',\n",
|
||
" sparse_output=False))]),\n",
|
||
" ['opt_in', 'gender_male', 'gender_female'])])</pre></div> </div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-12\" type=\"checkbox\" ><label for=\"sk-estimator-id-12\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">num</label><div class=\"sk-toggleable__content fitted\"><pre>['nb_tickets', 'nb_purchases', 'total_amount', 'nb_suppliers', 'vente_internet_max', 'purchase_date_min', 'purchase_date_max', 'time_between_purchase', 'nb_tickets_internet', 'nb_campaigns', 'nb_campaigns_opened']</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-13\" type=\"checkbox\" ><label for=\"sk-estimator-id-13\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> StandardScaler<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.preprocessing.StandardScaler.html\">?<span>Documentation for StandardScaler</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>StandardScaler()</pre></div> </div></div></div></div></div></div></div><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-14\" type=\"checkbox\" ><label for=\"sk-estimator-id-14\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">cat</label><div class=\"sk-toggleable__content fitted\"><pre>['opt_in', 'gender_male', 'gender_female']</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-15\" type=\"checkbox\" ><label for=\"sk-estimator-id-15\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> OneHotEncoder<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.preprocessing.OneHotEncoder.html\">?<span>Documentation for OneHotEncoder</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>OneHotEncoder(handle_unknown='ignore', sparse_output=False)</pre></div> </div></div></div></div></div></div></div></div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-16\" type=\"checkbox\" ><label for=\"sk-estimator-id-16\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> LogisticRegression<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.linear_model.LogisticRegression.html\">?<span>Documentation for LogisticRegression</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>LogisticRegression(max_iter=5000, solver='saga')</pre></div> </div></div></div></div></div></div></div></div></div></div></div>"
|
||
],
|
||
"text/plain": [
|
||
"GridSearchCV(cv=3, error_score='raise',\n",
|
||
" estimator=Pipeline(steps=[('preprocessor',\n",
|
||
" ColumnTransformer(transformers=[('num',\n",
|
||
" Pipeline(steps=[('scaler',\n",
|
||
" StandardScaler())]),\n",
|
||
" ['nb_tickets',\n",
|
||
" 'nb_purchases',\n",
|
||
" 'total_amount',\n",
|
||
" 'nb_suppliers',\n",
|
||
" 'vente_internet_max',\n",
|
||
" 'purchase_date_min',\n",
|
||
" 'purchase_date_max',\n",
|
||
" 'time_between_purchase',\n",
|
||
" 'nb_tickets_internet',\n",
|
||
" 'nb_campaigns',\n",
|
||
" 'nb_...\n",
|
||
" 1.562500e-02, 3.125000e-02, 6.250000e-02, 1.250000e-01,\n",
|
||
" 2.500000e-01, 5.000000e-01, 1.000000e+00, 2.000000e+00,\n",
|
||
" 4.000000e+00, 8.000000e+00, 1.600000e+01, 3.200000e+01,\n",
|
||
" 6.400000e+01]),\n",
|
||
" 'LogisticRegression_cv__class_weight': ['balanced',\n",
|
||
" {0.0: 0.5481283836040216,\n",
|
||
" 1.0: 5.694439980716696}],\n",
|
||
" 'LogisticRegression_cv__penalty': ['l1', 'l2']},\n",
|
||
" scoring=make_scorer(recall_score, response_method='predict'))"
|
||
]
|
||
},
|
||
"execution_count": 34,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"logit_cv = load_model(type_of_activity, \"LogisticRegression_cv\")\n",
|
||
"logit_cv"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "006819e7-e9c5-48d9-85ee-aa43d5e4c9c2",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Quartile clustering"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 35,
|
||
"id": "018d8ff4-3436-4eec-8507-d1a265cbabf1",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"y_pred = logit_cv.predict(X_test)\n",
|
||
"y_pred_prob = logit_cv.predict_proba(X_test)[:, 1]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 48,
|
||
"id": "846f53b9-73c2-4a8b-9d9e-f11bf59ce9ba",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1080/375041546.py:3: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" X_test_segment[\"has_purchased\"] = y_test\n",
|
||
"/tmp/ipykernel_1080/375041546.py:4: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" X_test_segment[\"has_purchased_estim\"] = y_pred\n",
|
||
"/tmp/ipykernel_1080/375041546.py:5: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" X_test_segment[\"score\"] = y_pred_prob\n",
|
||
"/tmp/ipykernel_1080/375041546.py:6: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" X_test_segment[\"quartile\"] = np.where(X_test['score']<0.25, '1',\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>nb_tickets</th>\n",
|
||
" <th>nb_purchases</th>\n",
|
||
" <th>total_amount</th>\n",
|
||
" <th>nb_suppliers</th>\n",
|
||
" <th>vente_internet_max</th>\n",
|
||
" <th>purchase_date_min</th>\n",
|
||
" <th>purchase_date_max</th>\n",
|
||
" <th>time_between_purchase</th>\n",
|
||
" <th>nb_tickets_internet</th>\n",
|
||
" <th>fidelity</th>\n",
|
||
" <th>...</th>\n",
|
||
" <th>gender_female</th>\n",
|
||
" <th>gender_male</th>\n",
|
||
" <th>gender_other</th>\n",
|
||
" <th>nb_campaigns</th>\n",
|
||
" <th>nb_campaigns_opened</th>\n",
|
||
" <th>has_purchased</th>\n",
|
||
" <th>has_purchased_estim</th>\n",
|
||
" <th>score</th>\n",
|
||
" <th>quartile</th>\n",
|
||
" <th>score_adjusted</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.425710</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.068441</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.442888</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.073036</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>40.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>508.227674</td>\n",
|
||
" <td>508.227674</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>4</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>12.0</td>\n",
|
||
" <td>5.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.293107</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.039474</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>10.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.062345</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.006547</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>4</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.421351</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.067312</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>5</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.248352</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.031709</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>6</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.054499</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.005680</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>7</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>6.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.058298</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.006098</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>8</th>\n",
|
||
" <td>6.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>126.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>390.374005</td>\n",
|
||
" <td>390.374005</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>6.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.098137</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.010670</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>9</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>10.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.062345</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.006547</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"<p>10 rows × 22 columns</p>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" nb_tickets nb_purchases total_amount nb_suppliers vente_internet_max \\\n",
|
||
"0 0.0 0.0 0.0 0.0 0.0 \n",
|
||
"1 0.0 0.0 0.0 0.0 0.0 \n",
|
||
"2 4.0 1.0 40.0 1.0 0.0 \n",
|
||
"3 0.0 0.0 0.0 0.0 0.0 \n",
|
||
"4 0.0 0.0 0.0 0.0 0.0 \n",
|
||
"5 0.0 0.0 0.0 0.0 0.0 \n",
|
||
"6 0.0 0.0 0.0 0.0 0.0 \n",
|
||
"7 0.0 0.0 0.0 0.0 0.0 \n",
|
||
"8 6.0 1.0 126.0 1.0 1.0 \n",
|
||
"9 0.0 0.0 0.0 0.0 0.0 \n",
|
||
"\n",
|
||
" purchase_date_min purchase_date_max time_between_purchase \\\n",
|
||
"0 550.000000 550.000000 -1.0 \n",
|
||
"1 550.000000 550.000000 -1.0 \n",
|
||
"2 508.227674 508.227674 0.0 \n",
|
||
"3 550.000000 550.000000 -1.0 \n",
|
||
"4 550.000000 550.000000 -1.0 \n",
|
||
"5 550.000000 550.000000 -1.0 \n",
|
||
"6 550.000000 550.000000 -1.0 \n",
|
||
"7 550.000000 550.000000 -1.0 \n",
|
||
"8 390.374005 390.374005 0.0 \n",
|
||
"9 550.000000 550.000000 -1.0 \n",
|
||
"\n",
|
||
" nb_tickets_internet fidelity ... gender_female gender_male \\\n",
|
||
"0 0.0 2 ... 1 0 \n",
|
||
"1 0.0 1 ... 1 0 \n",
|
||
"2 0.0 4 ... 1 0 \n",
|
||
"3 0.0 0 ... 0 0 \n",
|
||
"4 0.0 0 ... 1 0 \n",
|
||
"5 0.0 0 ... 0 0 \n",
|
||
"6 0.0 0 ... 0 0 \n",
|
||
"7 0.0 0 ... 0 0 \n",
|
||
"8 6.0 1 ... 0 1 \n",
|
||
"9 0.0 0 ... 0 0 \n",
|
||
"\n",
|
||
" gender_other nb_campaigns nb_campaigns_opened has_purchased \\\n",
|
||
"0 0 2.0 0.0 0.0 \n",
|
||
"1 0 2.0 1.0 0.0 \n",
|
||
"2 0 12.0 5.0 0.0 \n",
|
||
"3 1 10.0 0.0 0.0 \n",
|
||
"4 0 1.0 0.0 0.0 \n",
|
||
"5 1 2.0 0.0 0.0 \n",
|
||
"6 1 2.0 0.0 0.0 \n",
|
||
"7 1 6.0 0.0 0.0 \n",
|
||
"8 0 4.0 0.0 0.0 \n",
|
||
"9 1 10.0 0.0 0.0 \n",
|
||
"\n",
|
||
" has_purchased_estim score quartile score_adjusted \n",
|
||
"0 0.0 0.425710 2 0.068441 \n",
|
||
"1 0.0 0.442888 2 0.073036 \n",
|
||
"2 0.0 0.293107 2 0.039474 \n",
|
||
"3 0.0 0.062345 1 0.006547 \n",
|
||
"4 0.0 0.421351 2 0.067312 \n",
|
||
"5 0.0 0.248352 1 0.031709 \n",
|
||
"6 0.0 0.054499 1 0.005680 \n",
|
||
"7 0.0 0.058298 1 0.006098 \n",
|
||
"8 0.0 0.098137 1 0.010670 \n",
|
||
"9 0.0 0.062345 1 0.006547 \n",
|
||
"\n",
|
||
"[10 rows x 22 columns]"
|
||
]
|
||
},
|
||
"execution_count": 48,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test_segment = X_test\n",
|
||
"\n",
|
||
"X_test_segment[\"has_purchased\"] = y_test\n",
|
||
"X_test_segment[\"has_purchased_estim\"] = y_pred\n",
|
||
"X_test_segment[\"score\"] = y_pred_prob\n",
|
||
"X_test_segment[\"quartile\"] = np.where(X_test['score']<0.25, '1',\n",
|
||
" np.where(X_test['score']<0.5, '2',\n",
|
||
" np.where(X_test['score']<0.75, '3', '4')))\n",
|
||
"X_test_segment.head(10)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 50,
|
||
"id": "fb592fe3-ea40-4e83-8fe9-c52b9ee42f2a",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def df_segment(df, y, model) :\n",
|
||
"\n",
|
||
" y_pred = model.predict(df)\n",
|
||
" y_pred_prob = model.predict_proba(df)[:, 1]\n",
|
||
"\n",
|
||
" df_segment = df\n",
|
||
"\n",
|
||
" df_segment[\"has_purchased\"] = y\n",
|
||
" df_segment[\"has_purchased_estim\"] = y_pred\n",
|
||
" df_segment[\"score\"] = y_pred_prob\n",
|
||
" df_segment[\"quartile\"] = np.where(df_segment['score']<0.25, '1',\n",
|
||
" np.where(df_segment['score']<0.5, '2',\n",
|
||
" np.where(df_segment['score']<0.75, '3', '4')))\n",
|
||
"\n",
|
||
" return df_segment"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 51,
|
||
"id": "968645d5-58cc-485a-bd8b-99f4cfc26fec",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1080/2624515794.py:8: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" df_segment[\"has_purchased\"] = y\n",
|
||
"/tmp/ipykernel_1080/2624515794.py:9: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" df_segment[\"has_purchased_estim\"] = y_pred\n",
|
||
"/tmp/ipykernel_1080/2624515794.py:10: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" df_segment[\"score\"] = y_pred_prob\n",
|
||
"/tmp/ipykernel_1080/2624515794.py:11: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" df_segment[\"quartile\"] = np.where(df_segment['score']<0.25, '1',\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>nb_tickets</th>\n",
|
||
" <th>nb_purchases</th>\n",
|
||
" <th>total_amount</th>\n",
|
||
" <th>nb_suppliers</th>\n",
|
||
" <th>vente_internet_max</th>\n",
|
||
" <th>purchase_date_min</th>\n",
|
||
" <th>purchase_date_max</th>\n",
|
||
" <th>time_between_purchase</th>\n",
|
||
" <th>nb_tickets_internet</th>\n",
|
||
" <th>fidelity</th>\n",
|
||
" <th>...</th>\n",
|
||
" <th>gender_female</th>\n",
|
||
" <th>gender_male</th>\n",
|
||
" <th>gender_other</th>\n",
|
||
" <th>nb_campaigns</th>\n",
|
||
" <th>nb_campaigns_opened</th>\n",
|
||
" <th>has_purchased</th>\n",
|
||
" <th>has_purchased_estim</th>\n",
|
||
" <th>score</th>\n",
|
||
" <th>quartile</th>\n",
|
||
" <th>score_adjusted</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.425710</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.068441</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>2.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.442888</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.073036</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>40.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>508.227674</td>\n",
|
||
" <td>508.227674</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>4</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>12.0</td>\n",
|
||
" <td>5.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.293107</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.039474</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>10.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.062345</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.006547</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>4</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.421351</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.067312</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>...</th>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151869</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.258200</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.033348</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151870</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>8.0</td>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.538124</td>\n",
|
||
" <td>3</td>\n",
|
||
" <td>0.103520</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151871</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>14.0</td>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.548488</td>\n",
|
||
" <td>3</td>\n",
|
||
" <td>0.107461</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151872</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>16.0</td>\n",
|
||
" <td>3.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.179400</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.021208</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151873</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>11.0</td>\n",
|
||
" <td>8.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.220966</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.027343</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"<p>151874 rows × 22 columns</p>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" nb_tickets nb_purchases total_amount nb_suppliers \\\n",
|
||
"0 0.0 0.0 0.0 0.0 \n",
|
||
"1 0.0 0.0 0.0 0.0 \n",
|
||
"2 4.0 1.0 40.0 1.0 \n",
|
||
"3 0.0 0.0 0.0 0.0 \n",
|
||
"4 0.0 0.0 0.0 0.0 \n",
|
||
"... ... ... ... ... \n",
|
||
"151869 0.0 0.0 0.0 0.0 \n",
|
||
"151870 0.0 0.0 0.0 0.0 \n",
|
||
"151871 0.0 0.0 0.0 0.0 \n",
|
||
"151872 0.0 0.0 0.0 0.0 \n",
|
||
"151873 0.0 0.0 0.0 0.0 \n",
|
||
"\n",
|
||
" vente_internet_max purchase_date_min purchase_date_max \\\n",
|
||
"0 0.0 550.000000 550.000000 \n",
|
||
"1 0.0 550.000000 550.000000 \n",
|
||
"2 0.0 508.227674 508.227674 \n",
|
||
"3 0.0 550.000000 550.000000 \n",
|
||
"4 0.0 550.000000 550.000000 \n",
|
||
"... ... ... ... \n",
|
||
"151869 0.0 550.000000 550.000000 \n",
|
||
"151870 0.0 550.000000 550.000000 \n",
|
||
"151871 0.0 550.000000 550.000000 \n",
|
||
"151872 0.0 550.000000 550.000000 \n",
|
||
"151873 0.0 550.000000 550.000000 \n",
|
||
"\n",
|
||
" time_between_purchase nb_tickets_internet fidelity ... \\\n",
|
||
"0 -1.0 0.0 2 ... \n",
|
||
"1 -1.0 0.0 1 ... \n",
|
||
"2 0.0 0.0 4 ... \n",
|
||
"3 -1.0 0.0 0 ... \n",
|
||
"4 -1.0 0.0 0 ... \n",
|
||
"... ... ... ... ... \n",
|
||
"151869 -1.0 0.0 0 ... \n",
|
||
"151870 -1.0 0.0 0 ... \n",
|
||
"151871 -1.0 0.0 1 ... \n",
|
||
"151872 -1.0 0.0 0 ... \n",
|
||
"151873 -1.0 0.0 0 ... \n",
|
||
"\n",
|
||
" gender_female gender_male gender_other nb_campaigns \\\n",
|
||
"0 1 0 0 2.0 \n",
|
||
"1 1 0 0 2.0 \n",
|
||
"2 1 0 0 12.0 \n",
|
||
"3 0 0 1 10.0 \n",
|
||
"4 1 0 0 1.0 \n",
|
||
"... ... ... ... ... \n",
|
||
"151869 0 0 1 1.0 \n",
|
||
"151870 0 1 0 8.0 \n",
|
||
"151871 1 0 0 14.0 \n",
|
||
"151872 0 1 0 16.0 \n",
|
||
"151873 0 1 0 11.0 \n",
|
||
"\n",
|
||
" nb_campaigns_opened has_purchased has_purchased_estim score \\\n",
|
||
"0 0.0 0.0 0.0 0.425710 \n",
|
||
"1 1.0 0.0 0.0 0.442888 \n",
|
||
"2 5.0 0.0 0.0 0.293107 \n",
|
||
"3 0.0 0.0 0.0 0.062345 \n",
|
||
"4 0.0 0.0 0.0 0.421351 \n",
|
||
"... ... ... ... ... \n",
|
||
"151869 1.0 0.0 0.0 0.258200 \n",
|
||
"151870 4.0 0.0 1.0 0.538124 \n",
|
||
"151871 4.0 0.0 1.0 0.548488 \n",
|
||
"151872 3.0 0.0 0.0 0.179400 \n",
|
||
"151873 8.0 0.0 0.0 0.220966 \n",
|
||
"\n",
|
||
" quartile score_adjusted \n",
|
||
"0 2 0.068441 \n",
|
||
"1 2 0.073036 \n",
|
||
"2 2 0.039474 \n",
|
||
"3 1 0.006547 \n",
|
||
"4 2 0.067312 \n",
|
||
"... ... ... \n",
|
||
"151869 2 0.033348 \n",
|
||
"151870 3 0.103520 \n",
|
||
"151871 3 0.107461 \n",
|
||
"151872 1 0.021208 \n",
|
||
"151873 1 0.027343 \n",
|
||
"\n",
|
||
"[151874 rows x 22 columns]"
|
||
]
|
||
},
|
||
"execution_count": 51,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"df_segment(X_test, y_test, logit_cv)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "ad16b8ab-7e01-404b-971e-866e9b9d5aa4",
|
||
"metadata": {},
|
||
"source": [
|
||
"## definition of functions to compute the bias of scores and adjust it \n",
|
||
"\n",
|
||
"Le biais est calculé de la façon suivante. \n",
|
||
"En notant $\\hat{p(x_i)}$ le score calculé (estimé par la modélisation) et $p(x_i)$ le vrai score (sans biais), et $\\beta$ le logarithme du biais, on a : \\\n",
|
||
"$\\ln{\\frac{\\hat{p(x_i)}}{1-\\hat{p(x_i)}}} = \\beta + \\ln{\\frac{p(x_i)}{1-p(x_i)}}$ \\\n",
|
||
"$ \\frac{\\hat{p(x_i)}}{1-\\hat{p(x_i)}} = \\exp(\\beta) . \\frac{p(x_i)}{1-p(x_i)} $ , soit : \\\n",
|
||
"$p(x_i) = {\\frac{\\frac{\\hat{p(x_i)}}{1-\\hat{p(x_i)}}}{B+\\frac{\\hat{p(x_i)}}{1-\\hat{p(x_i)}}}}$ \\\n",
|
||
"Ce qu'on appelle biais et qu'on estime dans le code par la suite est : $B=\\exp(\\beta) $. Les probabilités ne sont donc pas biaisées si $B=1$. Il y a surestimation si $B>1$. \n",
|
||
"\n",
|
||
"On cherche le B qui permette d'ajuster les probabilités de telle sorte que la somme des scores soit égale à la somme des y_has_purchased. Cela revient à résoudre : \n",
|
||
"\n",
|
||
"\\begin{equation}\n",
|
||
"\\sum_{i}{\\frac{\\frac{\\hat{p(x_i)}}{1-\\hat{p(x_i)}}}{B+\\frac{\\hat{p(x_i)}}{1-\\hat{p(x_i)}}}} = \\sum_{i}{Y_i}\n",
|
||
"\\end{equation}\n",
|
||
"\n",
|
||
"C'est ce que fait la fonction find_bias. \n",
|
||
"\n",
|
||
"Note sur les notations : \\\n",
|
||
"$\\hat{p(x_i)}$ correspond à ce qu'on appelle le score et $p(x_i)$ à ce qu'on appellera le score adjusted"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 17,
|
||
"id": "f0379536-a6c5-4b16-bde5-d0319ec1b140",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# compute adjusted score from odd ratios (cf formula above)\n",
|
||
"def adjusted_score(odd_ratio, bias) :\n",
|
||
" adjusted_score = odd_ratio/(bias+odd_ratio)\n",
|
||
" return adjusted_score"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 18,
|
||
"id": "32a0dfd0-f49d-4785-a56f-706d381bfe41",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# when the score is 1 we cannot compute the odd ratio, so we adjust scores equal to 1\n",
|
||
"# we set the second best score instead\n",
|
||
"\n",
|
||
"def adjust_score_1(score) :\n",
|
||
" second_best_score = np.array([element for element in score if element !=1]).max()\n",
|
||
" new_score = np.array([element if element!=1 else second_best_score for element in score]) \n",
|
||
" return new_score"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 19,
|
||
"id": "2dff1def-02df-413e-afce-b4aeaf7752b6",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def odd_ratio(score) :\n",
|
||
" return score / (1 - score)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 20,
|
||
"id": "683d71fc-7442-4028-869c-49c57592d6e9",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# definition of a function that automatically detects the bias\n",
|
||
"\n",
|
||
"def find_bias(odd_ratios, y_objective, initial_guess=6) :\n",
|
||
" \"\"\"\n",
|
||
" results = minimize(lambda bias : (sum([adjusted_score(element, bias) for element in list(odd_ratios)]) - y_objective)**2 ,\n",
|
||
" initial_guess , method = \"BFGS\")\n",
|
||
"\n",
|
||
" estimated_bias = results.x[0]\n",
|
||
" \"\"\"\n",
|
||
"\n",
|
||
" # faster method\n",
|
||
" bias_estimated = fsolve(lambda bias : sum([adjusted_score(element, bias) for element in list(odd_ratios)]) - y_objective, x0=6)\n",
|
||
" \n",
|
||
" return bias_estimated[0]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 38,
|
||
"id": "781b0d40-c954-4c54-830a-e709c8667328",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"10.140994712235674"
|
||
]
|
||
},
|
||
"execution_count": 38,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"# computation with the function defined\n",
|
||
"\n",
|
||
"bias_test_set = find_bias(odd_ratios = odd_ratio(adjust_score_1(X_test_segment[\"score\"])), \n",
|
||
" y_objective = y_test[\"y_has_purchased\"].sum(),\n",
|
||
" initial_guess=6)\n",
|
||
"bias_test_set"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 39,
|
||
"id": "248cb862-418e-4767-9933-70c4885ecf40",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"10.089625954992135"
|
||
]
|
||
},
|
||
"execution_count": 39,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"# comparison with bias of the train set\n",
|
||
"X_train_score = logit_cv.predict_proba(X_train)[:, 1]\n",
|
||
"\n",
|
||
"bias_train_set = find_bias(odd_ratios = odd_ratio(adjust_score_1(X_train_score)), \n",
|
||
" y_objective = y_train[\"y_has_purchased\"].sum(),\n",
|
||
" initial_guess=6)\n",
|
||
"bias_train_set"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 40,
|
||
"id": "fff6cbe6-7bb3-4732-9b81-b9ac5383bbcf",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"betâ test - betâ train = 0.005078328390017222\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"print(\"betâ test - betâ train = \",np.log(bias_test_set/bias_train_set))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 41,
|
||
"id": "f506870d-4a8a-4b2c-8f0b-e0789080b20c",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"mean absolute erreur 0.00033179180098895215\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# impact of considering a bias computed on train set instead of test set - totally neglectable\n",
|
||
"\n",
|
||
"score_adjusted_test = adjusted_score(odd_ratio(adjust_score_1(X_test_segment[\"score\"])), bias = bias_test_set)\n",
|
||
"score_adjusted_train = adjusted_score(odd_ratio(adjust_score_1(X_test_segment[\"score\"])), bias = bias_train_set)\n",
|
||
"\n",
|
||
"print(\"mean absolute erreur\",abs(score_adjusted_test-score_adjusted_train).mean())"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 42,
|
||
"id": "8213d0e4-063b-49fa-90b7-677fc34f4c01",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipykernel_1080/1825363704.py:7: SettingWithCopyWarning: \n",
|
||
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
|
||
"Try using .loc[row_indexer,col_indexer] = value instead\n",
|
||
"\n",
|
||
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
|
||
" X_test_segment[\"score_adjusted\"] = score_adjusted_train\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# adjust scores accordingly \n",
|
||
"\n",
|
||
"# X_test_segment[\"score_adjusted\"] = adjusted_score(odd_ratio(adjust_score_1(X_test_segment[\"score\"])), bias = bias_test_set)\n",
|
||
"\n",
|
||
"# actually, we are not supposed to have X_test, so the biais is estimated on X_train\n",
|
||
"# X_test_segment[\"score_adjusted\"] = adjusted_score(odd_ratio(adjust_score_1(X_test_segment[\"score\"])), bias = bias_train_set)\n",
|
||
"X_test_segment[\"score_adjusted\"] = score_adjusted_train"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 43,
|
||
"id": "834d3723-2e72-4c65-9c62-e2d595c69461",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"MSE for score : 0.16848909203423532\n",
|
||
"MSE for ajusted score : 0.06481787838756012\n",
|
||
"sum of y_has_purchased : 13300.0\n",
|
||
"sum of adjusted scores : 13350.390547983186\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# check \n",
|
||
"\n",
|
||
"MSE_score = ((X_test_segment[\"score\"]-X_test_segment[\"has_purchased\"])**2).mean()\n",
|
||
"MSE_ajusted_score = ((X_test_segment[\"score_adjusted\"]-X_test_segment[\"has_purchased\"])**2).mean()\n",
|
||
"print(f\"MSE for score : {MSE_score}\")\n",
|
||
"print(f\"MSE for ajusted score : {MSE_ajusted_score}\")\n",
|
||
"\n",
|
||
"print(\"sum of y_has_purchased :\",y_test[\"y_has_purchased\"].sum())\n",
|
||
"print(\"sum of adjusted scores :\", X_test_segment[\"score_adjusted\"].sum())"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 44,
|
||
"id": "9f30a4dd-a9d8-405a-a7d5-5324ae88cf70",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"MAE for score : 0.3534914169353957\n",
|
||
"MAE for adjusted score : 0.13026115637615288\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# mean absolute error - divided by 2 with out method\n",
|
||
"\n",
|
||
"MAE_score = abs(X_test_segment[\"score\"]-X_test_segment[\"has_purchased\"]).mean()\n",
|
||
"MAE_ajusted_score = abs(X_test_segment[\"score_adjusted\"]-X_test_segment[\"has_purchased\"]).mean()\n",
|
||
"print(f\"MAE for score : {MAE_score}\")\n",
|
||
"print(f\"MAE for adjusted score : {MAE_ajusted_score}\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 28,
|
||
"id": "6f9396db-e213-408c-a596-eaeec3bc79f3",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# visualization\n",
|
||
"\n",
|
||
"# histogramme des probas et des probas ajustées\n",
|
||
"\n",
|
||
"def plot_hist_scores(df, score, score_adjusted, type_of_activity) :\n",
|
||
"\n",
|
||
" plt.figure()\n",
|
||
" plt.hist(df[score], label = \"score\", alpha=0.6)\n",
|
||
" plt.hist(df[score_adjusted], label=\"adjusted score\", alpha=0.6)\n",
|
||
" plt.legend()\n",
|
||
" plt.xlabel(\"probability of a future purchase\")\n",
|
||
" plt.ylabel(\"count\")\n",
|
||
" plt.title(f\"Comparison between score and adjusted score for {type_of_activity} companies\")\n",
|
||
" # plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 64,
|
||
"id": "def64c16-f4dd-493c-909c-d886d7f53947",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'projet-bdc2324-team1/Output_expected_CA/sport/hist_score_adjustedsport.png'"
|
||
]
|
||
},
|
||
"execution_count": 64,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"PATH + file_name + type_of_activity + \".png\""
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 45,
|
||
"id": "b478d40d-9677-4204-87bd-16fb0bc1fe9a",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"image/png": "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58+fx8mTJ9G3b18AQGxsLBISEuDs7CzNo62tDScnJ4SGhgIAoqKikJmZKYtRqVSws7OTYsLCwqBUKqWiEAA6duwIpVIpi7Gzs5OKQgBwcXFBeno6oqKiityG9PR0pKamyl5ERERE1ZFGVSdQnGnTpiElJQVNmzaFuro6srOz8d///heffPIJACAhIQEAYGZmJpvPzMwMt2/flmK0tLRgaGhYICZv/oSEBJiamhZYv6mpqSwm/3oMDQ2hpaUlxRQmICAAc+bMKc1mExEREVWJat1juG3bNmzevBlbt27F2bNnsXHjRixevBgbN26UxSkUCtmwEKLAuPzyxxQWX5aY/GbMmIGUlBTpFRcXV2xeRERERFWlWvcYTpkyBdOnT8fHH38MALC3t8ft27cREBCAoUOHwtzcHMCL3jwLCwtpvsTERKl3z9zcHBkZGUhKSpL1GiYmJqJTp05SzP379wus/8GDB7LlREREyKYnJSUhMzOzQE/iv2lra0NbW7ssm09ERERUqap1j+GzZ8+gpiZPUV1dXXpcTcOGDWFubo6QkBBpekZGBo4dOyYVfW3btoWmpqYsJj4+HpcuXZJiHBwckJKSgtOnT0sxERERSElJkcVcunQJ8fHxUkxwcDC0tbXRtm3bct5yIiIiospXrXsM3dzc8N///hf169dH8+bNce7cOSxduhTDhw8H8OLUrq+vL+bPn4/GjRujcePGmD9/PvT09ODu7g4AUCqVGDFiBPz8/GBkZIS6deti8uTJsLe3R8+ePQEAzZo1Q+/eveHl5YXvv/8eADBy5Ei4urrCxsYGAODs7AxbW1t4eHhg0aJFePToESZPngwvL6/X+u4kIiIienNU68Jw5cqVmDVrFry9vZGYmAiVSoVRo0bhyy+/lGKmTp2KtLQ0eHt7IykpCR06dEBwcDBq164txSxbtgwaGhoYNGgQ0tLS0KNHD2zYsAHq6upSzJYtW+Dj4yPdvdy/f3+sWrVKmq6uro59+/bB29sbjo6O0NXVhbu7OxYvXlwJLUFERERU8ar1cwxfR3yOYT58jiEREdUAfI4hEREREb1RWBgSEREREQAWhkRERESUi4UhEREREQFgYUhEREREuVgYEhEREREAFoZERERElIuFIREREREBYGFIRERERLlYGBIRERERABaGRERERJSLhSERERERAWBhSERERES5WBgS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d3csXry4graeiIiIqHLVqOcYvg74HEO5iNhHVZ1Cqe2uN7WqUyi1mvicOj7HsPLUxP2DqLLxOYZERERE9EZhYUhEREREAFgYEhEREVEuFoZEREREBICFIRERERHlYmFIRERERABYGBIRERFRLhaGRERERASAhSERERER5WJhSEREREQAWBgSERERUS4WhkREREQEgIUhEREREeXSqOoEiKjizdh5sapTICKiGoA9hkREREQEgIUhEREREeViYUhEREREAFgYEhEREVEuFoZEREREBICFIRERERHlYmFIRERERABYGBIRERFRLhaGRERERASAhSERERER5WJhSEREREQAWBgSERERUS4WhkREREQEgIUhEREREeXSqOoEqPxExD6q6hSIiIioBmOPIREREREBYGFIRERERLlYGBIRERERABaGRERERJSLN58QEVGNM2PnxapOodQCPrCv6hSIXoqFIVEpDbi7sKpTKLXd9aZWdQpERFQD8FQyEREREQFgYUhEREREuXgqmYjoDVcTr9cjoorBwpCIiKgS1MQCnDfMvHl4KpmIiIiIALAwJCIiIqJcLAyJiIiICACvMSQiIqIi8LrINw8LQ6I3AB/KTUREJcFTyUREREQEgIUhEREREeViYUhEREREAFgYEhEREVEu3nxSBt999x0WLVqE+Ph4NG/eHMuXL0fnzp2rOi2i10pNvGGmpuKNPkSUhz2GpbRt2zb4+vpi5syZOHfuHDp37ow+ffrgzp07VZ0aERER0SthYVhKS5cuxYgRI/D555+jWbNmWL58OaysrLB69eqqTo2IiIjolfBUcilkZGQgKioK06dPl413dnZGaGhoFWVFRPRqeNq+ctTEU/Y1c9/YVNUJ1GgsDEvhn3/+QXZ2NszMzGTjzczMkJCQUOg86enpSE9Pl4ZTUlIAAKmpqeWe39PnGeW+TCIiKh+9/pxX1SmU2tOqTqAMKuL79d/LFUJUyPKrCxaGZaBQKGTDQogC4/IEBARgzpw5BcZbWVlVSG5ERERvtGnbK3Txjx8/hlKprNB1VCUWhqVgbGwMdXX1Ar2DiYmJBXoR88yYMQOTJk2ShnNycvDo0SMYGRkVWUyWRWpqKqysrBAXFwcDA4NyWy7JsZ0rB9u58rCtKwfbuXJUZDsLIfD48WOoVKpyXW51w8KwFLS0tNC2bVuEhITg/fff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1xd//PEHYmNjcfbsWRw+fFj6Q2Ds2LF49OgRPvnkE5w+fRp//fUXgoODMXz48EL/ECF6U7EwJKrmhgwZgrS0NLRv3x5jx47F+PHjMXLkyGLnadOmDbZv347AwEDY2dnhyy+/xNy5cwvcTevn54eoqCi0bt0aX331FZYsWQIXFxcAQKtWrbB06VIsWLAAdnZ22LJlCwICAgqsS09PD9OmTYO7uzscHBygq6uLwMDAMm/v3LlzcevWLbz11lswMTGRTRsxYgQyMjIwfPjwly7n66+/xocffggPDw+0adMGf/75J/744w8YGhqWOBcTExNs2LABv/zyC2xtbfH1119j8eLFpd4mAFiyZAmsrKzQpUsXuLu7Y/LkydDT05Oma2hoYMWKFfj++++hUqnw3nvvAQCGDx+OoUOHYsiQIXByckLDhg3RrVu3l66vRYsWOHbsGG7cuIHOnTujdevWmDVrFiwsLIqd7+2338YHH3yAvn37wtnZGXZ2dvjuu++k6WXNp0mTJggODsb58+fRvn17ODg44LfffoOGRskep1uS/TE7Oxtjx45Fs2bN0Lt3b9jY2Ei5q1QqnDp1CtnZ2XBxcYGdnR0mTJgApVIJNTV+FRLlUYiSXnhERJWua9euaNWqVaX9Ekh1t2XLFkyYMAH37t3jA5MrgL+/P3bv3s1fXyF6g/GXT4io2nv27BliY2MREBCAUaNGsSgkIqog7D8nompv4cKFaNWqFczMzDBjxoyqToeI6LXFU8lEREREBIA9hkRERESUi4UhEREREQFgYUhEREREuVgYEhEREREAFoZERERElIuFIREREREBYGFIRERERLlYGBIRERERABaGRERERJTr/wC61vLbQFJeSQAAAABJRU5ErkJggg==",
|
||
"text/plain": [
|
||
"<Figure size 640x480 with 1 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"plot_hist_scores(X_test_segment, score = \"score\", score_adjusted = \"score_adjusted\", type_of_activity = type_of_activity)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 40,
|
||
"id": "add631d7-0757-45a5-bb5b-f7f4b4baa961",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"projet-bdc2324-team1/Output_expected_CA/sport/\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# define path so save graphics\n",
|
||
"\n",
|
||
"# define type of activity \n",
|
||
"type_of_activity = \"sport\"\n",
|
||
"PATH = f\"projet-bdc2324-team1/Output_expected_CA/{type_of_activity}/\"\n",
|
||
"print(PATH)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 68,
|
||
"id": "3a5b5bd9-e033-4436-8c56-bf5fb61df87f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# export png \n",
|
||
"\n",
|
||
"# plot adjusted scores and save (to be tested)\n",
|
||
"plot_hist_scores(X_test_segment, score = \"score\", score_adjusted = \"score_adjusted\", type_of_activity = type_of_activity)\n",
|
||
"\n",
|
||
"image_buffer = io.BytesIO()\n",
|
||
"plt.savefig(image_buffer, format='png')\n",
|
||
"image_buffer.seek(0)\n",
|
||
"file_name = \"hist_score_adjusted_\"\n",
|
||
"FILE_PATH_OUT_S3 = PATH + file_name + type_of_activity + \".png\"\n",
|
||
"with fs.open(FILE_PATH_OUT_S3, 'wb') as s3_file:\n",
|
||
" s3_file.write(image_buffer.read())\n",
|
||
"plt.close()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "e6fae260-fab8-4f51-90dc-9b6d7314c77b",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Compute number of tickets and CA by segment with the recalibrated score"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 46,
|
||
"id": "90c4c2b5-0ede-4001-889f-749cfbd9df04",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>quartile</th>\n",
|
||
" <th>score (%)</th>\n",
|
||
" <th>score adjusted (%)</th>\n",
|
||
" <th>has purchased (%)</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>1</td>\n",
|
||
" <td>14.62</td>\n",
|
||
" <td>1.70</td>\n",
|
||
" <td>2.04</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>2</td>\n",
|
||
" <td>39.16</td>\n",
|
||
" <td>6.22</td>\n",
|
||
" <td>5.24</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>3</td>\n",
|
||
" <td>58.11</td>\n",
|
||
" <td>12.64</td>\n",
|
||
" <td>12.57</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>4</td>\n",
|
||
" <td>86.09</td>\n",
|
||
" <td>43.12</td>\n",
|
||
" <td>45.98</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" quartile score (%) score adjusted (%) has purchased (%)\n",
|
||
"0 1 14.62 1.70 2.04\n",
|
||
"1 2 39.16 6.22 5.24\n",
|
||
"2 3 58.11 12.64 12.57\n",
|
||
"3 4 86.09 43.12 45.98"
|
||
]
|
||
},
|
||
"execution_count": 46,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test_table_adjusted_scores = (100 * X_test_segment.groupby(\"quartile\")[[\"score\",\"score_adjusted\", \"has_purchased\"]].mean()).round(2).reset_index()\n",
|
||
"X_test_table_adjusted_scores = X_test_table_adjusted_scores.rename(columns = {col : f\"{col.replace('_', ' ')} (%)\" for col in X_test_table_adjusted_scores.columns if col in [\"score\",\"score_adjusted\", \"has_purchased\"]})\n",
|
||
"X_test_table_adjusted_scores"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 162,
|
||
"id": "d0b8740c-cf48-4a3e-83cb-23d95059f62f",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'\\\\begin{tabular}{lrrr}\\n\\\\toprule\\nquartile & score (%) & score adjusted (%) & has purchased (%) \\\\\\\\\\n\\\\midrule\\n1 & 13.250000 & 2.510000 & 1.570000 \\\\\\\\\\n2 & 33.890000 & 8.000000 & 9.850000 \\\\\\\\\\n3 & 63.060000 & 22.580000 & 21.470000 \\\\\\\\\\n4 & 90.520000 & 66.200000 & 65.010000 \\\\\\\\\\n\\\\bottomrule\\n\\\\end{tabular}\\n'"
|
||
]
|
||
},
|
||
"execution_count": 162,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test_table_adjusted_scores.to_latex(index=False)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 43,
|
||
"id": "d6a04d3e-c454-43e4-ae4c-0746e928575b",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# comparison between score and adjusted score - export csv associated\n",
|
||
"\n",
|
||
"file_name = \"table_adjusted_score_\"\n",
|
||
"FILE_PATH_OUT_S3 = PATH + file_name + type_of_activity + \".csv\"\n",
|
||
"with fs.open(FILE_PATH_OUT_S3, 'w') as file_out:\n",
|
||
" X_test_table_adjusted_scores.to_csv(file_out, index = False)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 59,
|
||
"id": "a974589f-7952-4db2-bebf-7b69c6b09372",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def project_tickets_CA (df, nb_purchases, nb_tickets, total_amount, score_adjusted, duration_ref, duration_projection) :\n",
|
||
" \n",
|
||
" duration_ratio = duration_ref/duration_projection\n",
|
||
"\n",
|
||
" df_output = df\n",
|
||
"\n",
|
||
" df_output.loc[:,\"nb_tickets_projected\"] = df_output.loc[:,nb_tickets] / duration_ratio\n",
|
||
" df_output.loc[:,\"total_amount_projected\"] = df_output.loc[:,total_amount] / duration_ratio\n",
|
||
" \n",
|
||
" df_output.loc[:,\"nb_tickets_expected\"] = df_output.loc[:,score_adjusted] * df_output.loc[:,\"nb_tickets_projected\"]\n",
|
||
" df_output.loc[:,\"total_amount_expected\"] = df_output.loc[:,score_adjusted] * df_output.loc[:,\"total_amount_projected\"]\n",
|
||
"\n",
|
||
" df_output.loc[:,\"pace_purchase\"] = (duration_ref/df_output.loc[:,nb_purchases]).apply(lambda x : np.nan if x==np.inf else x)\n",
|
||
" \n",
|
||
" return df_output\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 67,
|
||
"id": "dd8a52e1-d06e-4790-8687-8e58e3e6b84e",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>nb_tickets</th>\n",
|
||
" <th>nb_purchases</th>\n",
|
||
" <th>total_amount</th>\n",
|
||
" <th>nb_suppliers</th>\n",
|
||
" <th>vente_internet_max</th>\n",
|
||
" <th>purchase_date_min</th>\n",
|
||
" <th>purchase_date_max</th>\n",
|
||
" <th>time_between_purchase</th>\n",
|
||
" <th>nb_tickets_internet</th>\n",
|
||
" <th>fidelity</th>\n",
|
||
" <th>...</th>\n",
|
||
" <th>has_purchased</th>\n",
|
||
" <th>has_purchased_estim</th>\n",
|
||
" <th>score</th>\n",
|
||
" <th>quartile</th>\n",
|
||
" <th>score_adjusted</th>\n",
|
||
" <th>nb_tickets_projected</th>\n",
|
||
" <th>total_amount_projected</th>\n",
|
||
" <th>nb_tickets_expected</th>\n",
|
||
" <th>total_amount_expected</th>\n",
|
||
" <th>pace_purchase</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.425710</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.068441</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.442888</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.073036</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>4.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>40.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>508.227674</td>\n",
|
||
" <td>508.227674</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>4</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.293107</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.039474</td>\n",
|
||
" <td>2.823529</td>\n",
|
||
" <td>28.235294</td>\n",
|
||
" <td>0.111455</td>\n",
|
||
" <td>1.11455</td>\n",
|
||
" <td>17.0</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.062345</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.006547</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>4</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.421351</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.067312</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>...</th>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151869</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.258200</td>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.033348</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151870</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.538124</td>\n",
|
||
" <td>3</td>\n",
|
||
" <td>0.103520</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151871</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>1.0</td>\n",
|
||
" <td>0.548488</td>\n",
|
||
" <td>3</td>\n",
|
||
" <td>0.107461</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151872</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.179400</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.021208</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>151873</th>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>550.000000</td>\n",
|
||
" <td>-1.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.0</td>\n",
|
||
" <td>0.220966</td>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.027343</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.00000</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"<p>151874 rows × 27 columns</p>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" nb_tickets nb_purchases total_amount nb_suppliers \\\n",
|
||
"0 0.0 0.0 0.0 0.0 \n",
|
||
"1 0.0 0.0 0.0 0.0 \n",
|
||
"2 4.0 1.0 40.0 1.0 \n",
|
||
"3 0.0 0.0 0.0 0.0 \n",
|
||
"4 0.0 0.0 0.0 0.0 \n",
|
||
"... ... ... ... ... \n",
|
||
"151869 0.0 0.0 0.0 0.0 \n",
|
||
"151870 0.0 0.0 0.0 0.0 \n",
|
||
"151871 0.0 0.0 0.0 0.0 \n",
|
||
"151872 0.0 0.0 0.0 0.0 \n",
|
||
"151873 0.0 0.0 0.0 0.0 \n",
|
||
"\n",
|
||
" vente_internet_max purchase_date_min purchase_date_max \\\n",
|
||
"0 0.0 550.000000 550.000000 \n",
|
||
"1 0.0 550.000000 550.000000 \n",
|
||
"2 0.0 508.227674 508.227674 \n",
|
||
"3 0.0 550.000000 550.000000 \n",
|
||
"4 0.0 550.000000 550.000000 \n",
|
||
"... ... ... ... \n",
|
||
"151869 0.0 550.000000 550.000000 \n",
|
||
"151870 0.0 550.000000 550.000000 \n",
|
||
"151871 0.0 550.000000 550.000000 \n",
|
||
"151872 0.0 550.000000 550.000000 \n",
|
||
"151873 0.0 550.000000 550.000000 \n",
|
||
"\n",
|
||
" time_between_purchase nb_tickets_internet fidelity ... \\\n",
|
||
"0 -1.0 0.0 2 ... \n",
|
||
"1 -1.0 0.0 1 ... \n",
|
||
"2 0.0 0.0 4 ... \n",
|
||
"3 -1.0 0.0 0 ... \n",
|
||
"4 -1.0 0.0 0 ... \n",
|
||
"... ... ... ... ... \n",
|
||
"151869 -1.0 0.0 0 ... \n",
|
||
"151870 -1.0 0.0 0 ... \n",
|
||
"151871 -1.0 0.0 1 ... \n",
|
||
"151872 -1.0 0.0 0 ... \n",
|
||
"151873 -1.0 0.0 0 ... \n",
|
||
"\n",
|
||
" has_purchased has_purchased_estim score quartile \\\n",
|
||
"0 0.0 0.0 0.425710 2 \n",
|
||
"1 0.0 0.0 0.442888 2 \n",
|
||
"2 0.0 0.0 0.293107 2 \n",
|
||
"3 0.0 0.0 0.062345 1 \n",
|
||
"4 0.0 0.0 0.421351 2 \n",
|
||
"... ... ... ... ... \n",
|
||
"151869 0.0 0.0 0.258200 2 \n",
|
||
"151870 0.0 1.0 0.538124 3 \n",
|
||
"151871 0.0 1.0 0.548488 3 \n",
|
||
"151872 0.0 0.0 0.179400 1 \n",
|
||
"151873 0.0 0.0 0.220966 1 \n",
|
||
"\n",
|
||
" score_adjusted nb_tickets_projected total_amount_projected \\\n",
|
||
"0 0.068441 0.000000 0.000000 \n",
|
||
"1 0.073036 0.000000 0.000000 \n",
|
||
"2 0.039474 2.823529 28.235294 \n",
|
||
"3 0.006547 0.000000 0.000000 \n",
|
||
"4 0.067312 0.000000 0.000000 \n",
|
||
"... ... ... ... \n",
|
||
"151869 0.033348 0.000000 0.000000 \n",
|
||
"151870 0.103520 0.000000 0.000000 \n",
|
||
"151871 0.107461 0.000000 0.000000 \n",
|
||
"151872 0.021208 0.000000 0.000000 \n",
|
||
"151873 0.027343 0.000000 0.000000 \n",
|
||
"\n",
|
||
" nb_tickets_expected total_amount_expected pace_purchase \n",
|
||
"0 0.000000 0.00000 NaN \n",
|
||
"1 0.000000 0.00000 NaN \n",
|
||
"2 0.111455 1.11455 17.0 \n",
|
||
"3 0.000000 0.00000 NaN \n",
|
||
"4 0.000000 0.00000 NaN \n",
|
||
"... ... ... ... \n",
|
||
"151869 0.000000 0.00000 NaN \n",
|
||
"151870 0.000000 0.00000 NaN \n",
|
||
"151871 0.000000 0.00000 NaN \n",
|
||
"151872 0.000000 0.00000 NaN \n",
|
||
"151873 0.000000 0.00000 NaN \n",
|
||
"\n",
|
||
"[151874 rows x 27 columns]"
|
||
]
|
||
},
|
||
"execution_count": 67,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test_segment = project_tickets_CA (X_test_segment, \"nb_purchases\", \"nb_tickets\", \"total_amount\", \"score_adjusted\", \n",
|
||
" duration_ref=17, duration_projection=12)\n",
|
||
"X_test_segment"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 61,
|
||
"id": "cb66a8ea-65f7-460f-b3fc-ba76a3b91faa",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"quartile\n",
|
||
"1 16.475616\n",
|
||
"2 16.474062\n",
|
||
"3 15.707271\n",
|
||
"4 11.484654\n",
|
||
"Name: pace_purchase, dtype: float64"
|
||
]
|
||
},
|
||
"execution_count": 61,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test_segment.groupby(\"quartile\")[\"pace_purchase\"].mean()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 63,
|
||
"id": "f58f9151-2f91-45df-abb7-1ddcf0652adc",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# generalization with a function\n",
|
||
"\n",
|
||
"def summary_expected_CA(df, segment, nb_tickets_expected, total_amount_expected, total_amount, pace_purchase,\n",
|
||
" duration_ref=17, duration_projection=12) :\n",
|
||
" \n",
|
||
" # compute nb tickets estimated and total amount expected\n",
|
||
" df_expected_CA = df.groupby(segment)[[nb_tickets_expected, total_amount_expected]].sum().reset_index()\n",
|
||
" \n",
|
||
" # number of customers by segment\n",
|
||
" df_expected_CA.insert(1, \"size\", df.groupby(segment).size().values)\n",
|
||
" \n",
|
||
" # size in percent of all customers\n",
|
||
" df_expected_CA.insert(2, \"size_perct\", 100 * df_expected_CA[\"size\"]/df_expected_CA[\"size\"].sum())\n",
|
||
" \n",
|
||
" # compute share of CA recovered\n",
|
||
" duration_ratio=duration_ref/duration_projection\n",
|
||
" \n",
|
||
" df_expected_CA[\"revenue_recovered_perct\"] = 100 * duration_ratio * df_expected_CA[total_amount_expected] / \\\n",
|
||
" df.groupby(segment)[total_amount].sum().values\n",
|
||
"\n",
|
||
" df_drop_null_pace = df.dropna(subset=[pace_purchase])\n",
|
||
" df_expected_CA[\"pace_purchase\"] = df_drop_null_pace.groupby(segment)[pace_purchase].mean().values\n",
|
||
" \n",
|
||
" return df_expected_CA"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 68,
|
||
"id": "c8df6c80-43e8-4f00-9cd3-eb9022744313",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>quartile</th>\n",
|
||
" <th>size</th>\n",
|
||
" <th>size_perct</th>\n",
|
||
" <th>nb_tickets_expected</th>\n",
|
||
" <th>total_amount_expected</th>\n",
|
||
" <th>revenue_recovered_perct</th>\n",
|
||
" <th>pace_purchase</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>1</td>\n",
|
||
" <td>53626</td>\n",
|
||
" <td>35.31</td>\n",
|
||
" <td>398.26</td>\n",
|
||
" <td>13949.33</td>\n",
|
||
" <td>2.35</td>\n",
|
||
" <td>16.48</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>2</td>\n",
|
||
" <td>55974</td>\n",
|
||
" <td>36.86</td>\n",
|
||
" <td>3113.77</td>\n",
|
||
" <td>101639.45</td>\n",
|
||
" <td>6.24</td>\n",
|
||
" <td>16.47</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>3</td>\n",
|
||
" <td>30435</td>\n",
|
||
" <td>20.04</td>\n",
|
||
" <td>6214.35</td>\n",
|
||
" <td>208267.22</td>\n",
|
||
" <td>14.27</td>\n",
|
||
" <td>15.71</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>4</td>\n",
|
||
" <td>11839</td>\n",
|
||
" <td>7.80</td>\n",
|
||
" <td>72929.46</td>\n",
|
||
" <td>1835702.43</td>\n",
|
||
" <td>75.38</td>\n",
|
||
" <td>11.48</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" quartile size size_perct nb_tickets_expected total_amount_expected \\\n",
|
||
"0 1 53626 35.31 398.26 13949.33 \n",
|
||
"1 2 55974 36.86 3113.77 101639.45 \n",
|
||
"2 3 30435 20.04 6214.35 208267.22 \n",
|
||
"3 4 11839 7.80 72929.46 1835702.43 \n",
|
||
"\n",
|
||
" revenue_recovered_perct pace_purchase \n",
|
||
"0 2.35 16.48 \n",
|
||
"1 6.24 16.47 \n",
|
||
"2 14.27 15.71 \n",
|
||
"3 75.38 11.48 "
|
||
]
|
||
},
|
||
"execution_count": 68,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test_expected_CA = round(summary_expected_CA(df=X_test_segment, segment=\"quartile\", \n",
|
||
" nb_tickets_expected=\"nb_tickets_expected\", total_amount_expected=\"total_amount_expected\", \n",
|
||
" total_amount=\"total_amount\", pace_purchase=\"pace_purchase\"),2)\n",
|
||
"\n",
|
||
"X_test_expected_CA"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 64,
|
||
"id": "ac706ed7-defa-4df1-82e1-06f12fc1b6ad",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'\\\\begin{tabular}{lrrrrrr}\\n\\\\toprule\\nquartile & size & size (%) & nb tickets expected & total amount expected & revenue recovered (%) & pace purchase \\\\\\\\\\n\\\\midrule\\n1 & 53626 & 35.310000 & 398.260000 & 13949.330000 & 2.350000 & 16.480000 \\\\\\\\\\n2 & 55974 & 36.860000 & 3113.770000 & 101639.450000 & 6.240000 & 16.470000 \\\\\\\\\\n3 & 30435 & 20.040000 & 6214.350000 & 208267.220000 & 14.270000 & 15.710000 \\\\\\\\\\n4 & 11839 & 7.800000 & 72929.460000 & 1835702.430000 & 75.380000 & 11.480000 \\\\\\\\\\n\\\\bottomrule\\n\\\\end{tabular}\\n'"
|
||
]
|
||
},
|
||
"execution_count": 64,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"# Création du dictionnaire de mapping pour les noms de colonnes\n",
|
||
"mapping_dict = {col: col.replace(\"perct\", \"(%)\").replace(\"_\", \" \") for col in X_test_expected_CA.columns}\n",
|
||
"\n",
|
||
"X_test_expected_CA.rename(columns=mapping_dict).to_latex(index=False)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 122,
|
||
"id": "771da0cf-c49f-4e7e-b52f-ebcfb0fb2df3",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# export summary table to the MinIO storage\n",
|
||
"\n",
|
||
"file_name = \"table_expected_CA_\"\n",
|
||
"FILE_PATH_OUT_S3 = PATH + file_name + type_of_activity + \".csv\"\n",
|
||
"with fs.open(FILE_PATH_OUT_S3, 'w') as file_out:\n",
|
||
" X_test_expected_CA.to_csv(file_out, index = False)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 53,
|
||
"id": "c805dc10-4d07-4f7d-a677-5461a92845d7",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'projet-bdc2324-team1/Output_expected_CA/musique/table_expected_CA_musique.csv'"
|
||
]
|
||
},
|
||
"execution_count": 53,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"PATH = f\"projet-bdc2324-team1/Output_expected_CA/{type_of_activity}/\"\n",
|
||
"file_name = \"table_expected_CA_\"\n",
|
||
"FILE_PATH_OUT_S3 = PATH + file_name + type_of_activity + \".csv\"\n",
|
||
"FILE_PATH_OUT_S3"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "e35ccfff-1845-41f0-9bde-f09b09b67877",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Test : vizu tables saved"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 66,
|
||
"id": "4e9e88e4-ea10-41f4-9bf1-20b55269a20d",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>quartile</th>\n",
|
||
" <th>score (%)</th>\n",
|
||
" <th>score adjusted (%)</th>\n",
|
||
" <th>has purchased (%)</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>1</td>\n",
|
||
" <td>13.25</td>\n",
|
||
" <td>2.51</td>\n",
|
||
" <td>1.57</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>2</td>\n",
|
||
" <td>33.89</td>\n",
|
||
" <td>8.00</td>\n",
|
||
" <td>9.85</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>3</td>\n",
|
||
" <td>63.06</td>\n",
|
||
" <td>22.58</td>\n",
|
||
" <td>21.47</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>4</td>\n",
|
||
" <td>90.52</td>\n",
|
||
" <td>66.20</td>\n",
|
||
" <td>65.01</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" quartile score (%) score adjusted (%) has purchased (%)\n",
|
||
"0 1 13.25 2.51 1.57\n",
|
||
"1 2 33.89 8.00 9.85\n",
|
||
"2 3 63.06 22.58 21.47\n",
|
||
"3 4 90.52 66.20 65.01"
|
||
]
|
||
},
|
||
"execution_count": 66,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"path = 'projet-bdc2324-team1/Output_expected_CA/sport/table_adjusted_scoresport.csv'\n",
|
||
"\n",
|
||
"with fs.open( path, mode=\"rb\") as file_in:\n",
|
||
" df = pd.read_csv(file_in, sep=\",\")\n",
|
||
"df"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "9c471bdd-25c2-420a-a8a1-3add9f003cbc",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Just to try, same computation with score instead of score adjusted\n",
|
||
"\n",
|
||
"seems overestimated : if only 14% of customers come back, how can we recover 22% of the revenue from the segment that is least likely to buy ?? ..."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 80,
|
||
"id": "53684a24-1809-465f-8e21-b9295e34582a",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>quartile</th>\n",
|
||
" <th>size</th>\n",
|
||
" <th>size_perct</th>\n",
|
||
" <th>nb_tickets_expected</th>\n",
|
||
" <th>total_amount_expected</th>\n",
|
||
" <th>perct_revenue_recovered</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>1</td>\n",
|
||
" <td>37410</td>\n",
|
||
" <td>38.93</td>\n",
|
||
" <td>419.76</td>\n",
|
||
" <td>9245.08</td>\n",
|
||
" <td>21.71</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>2</td>\n",
|
||
" <td>29517</td>\n",
|
||
" <td>30.72</td>\n",
|
||
" <td>11549.06</td>\n",
|
||
" <td>296522.02</td>\n",
|
||
" <td>39.24</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>3</td>\n",
|
||
" <td>20137</td>\n",
|
||
" <td>20.96</td>\n",
|
||
" <td>29997.85</td>\n",
|
||
" <td>954751.91</td>\n",
|
||
" <td>63.34</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>4</td>\n",
|
||
" <td>9032</td>\n",
|
||
" <td>9.40</td>\n",
|
||
" <td>244655.82</td>\n",
|
||
" <td>10736011.95</td>\n",
|
||
" <td>97.72</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>"
|
||
],
|
||
"text/plain": [
|
||
" quartile size size_perct nb_tickets_expected total_amount_expected \\\n",
|
||
"0 1 37410 38.93 419.76 9245.08 \n",
|
||
"1 2 29517 30.72 11549.06 296522.02 \n",
|
||
"2 3 20137 20.96 29997.85 954751.91 \n",
|
||
"3 4 9032 9.40 244655.82 10736011.95 \n",
|
||
"\n",
|
||
" perct_revenue_recovered \n",
|
||
"0 21.71 \n",
|
||
"1 39.24 \n",
|
||
"2 63.34 \n",
|
||
"3 97.72 "
|
||
]
|
||
},
|
||
"execution_count": 80,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test_segment_bis = project_tickets_CA (X_test_segment, \"nb_tickets\", \"total_amount\", \"score\", duration_ref=1.5, duration_projection=1)\n",
|
||
"\n",
|
||
"X_test_expected_CA_bis = round(summary_expected_CA(df=X_test_segment_bis, segment=\"quartile\", nb_tickets_expected=\"nb_tickets_expected\", \n",
|
||
" total_amount_expected=\"total_amount_expected\", total_amount=\"total_amount\"),2)\n",
|
||
"\n",
|
||
"X_test_expected_CA_bis"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 81,
|
||
"id": "7dc66d1e-da03-4513-96e4-d9a43ac0a2c8",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"overall share of revenue recovered : 90.26 %\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"print(\"overall share of revenue recovered : \", round(100 * duration_ratio * X_test_expected_CA_bis[\"total_amount_expected\"].sum() / \\\n",
|
||
"X_test_segment_bis[\"total_amount\"].sum(),2), \"%\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "673f2969-7b9a-44c1-abf5-5679fca877ce",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Last pieces of analysis"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 161,
|
||
"id": "2365bb13-0f3f-49d5-bf91-52c92abebcee",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"overall share of revenue recovered : 77.64%\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# global revenue recovered\n",
|
||
"global_revenue_recovered = round(100 * duration_ratio * X_test_expected_CA[\"total_amount_expected\"].sum() / \\\n",
|
||
"X_test_segment[\"total_amount\"].sum(),2)\n",
|
||
"print(f\"overall share of revenue recovered : {global_revenue_recovered}%\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 163,
|
||
"id": "16b17f35-57dd-459a-8989-129143dc0952",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"0 0.018093\n",
|
||
"1 0.721519\n",
|
||
"2 3.336101\n",
|
||
"3 95.924287\n",
|
||
"Name: total_amount_expected, dtype: float64"
|
||
]
|
||
},
|
||
"execution_count": 163,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"100 * X_test_expected_CA[\"total_amount_expected\"]/X_test_expected_CA[\"total_amount_expected\"].sum()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 166,
|
||
"id": "dee4a200-eefe-4377-8e80-59ad33edd3c0",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"quartile\n",
|
||
"1 0.320407\n",
|
||
"2 5.685020\n",
|
||
"3 11.339715\n",
|
||
"4 82.654858\n",
|
||
"Name: total_amount, dtype: float64"
|
||
]
|
||
},
|
||
"execution_count": 166,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"# le segment 4 représente 83% du CA actuel et 96% du CA lié aux anciens clients pour l'année prochaine\n",
|
||
"100 * X_test_segment.groupby(\"quartile\")[\"total_amount\"].sum()/X_test_segment[\"total_amount\"].sum()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 177,
|
||
"id": "c1e6f020-ef18-40b4-bfc1-19f98cb2796e",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"count 96096.000000\n",
|
||
"mean 207.475735\n",
|
||
"std 4720.046248\n",
|
||
"min -48831.800000\n",
|
||
"25% 0.000000\n",
|
||
"50% 0.000000\n",
|
||
"75% 60.000000\n",
|
||
"max 624890.000000\n",
|
||
"Name: total_amount, dtype: float64"
|
||
]
|
||
},
|
||
"execution_count": 177,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"X_test_segment[\"total_amount\"].describe() # total amount négatif ???\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 184,
|
||
"id": "d301a50e-7c68-40f0-9245-a4eea64c387b",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"0 -4.883180e+04\n",
|
||
"1 -6.483180e+04\n",
|
||
"2 -7.683860e+04\n",
|
||
"3 -8.683860e+04\n",
|
||
"4 -9.683860e+04\n",
|
||
" ... \n",
|
||
"96091 1.802247e+07\n",
|
||
"96092 1.839238e+07\n",
|
||
"96093 1.877219e+07\n",
|
||
"96094 1.931270e+07\n",
|
||
"96095 1.993759e+07\n",
|
||
"Name: total_amount, Length: 96096, dtype: float64"
|
||
]
|
||
},
|
||
"execution_count": 184,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"np.cumsum(X_test_segment[\"total_amount\"].sort_values()).reset_index()[\"total_amount\"]"
|
||
]
|
||
}
|
||
],
|
||
"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.11.6"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|