{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f1effad2-9b66-4c86-964b-bb2059f37041",
   "metadata": {},
   "outputs": [],
   "source": [
    "#!pip -q install snowflake-connector-python pytest pytest-sugar "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "2de8b384",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\r\n",
      "black 23.7.0 requires packaging>=22.0, but you have packaging 21.3 which is incompatible.\r\n",
      "sparkmagic 0.20.5 requires nest-asyncio==1.5.5, but you have nest-asyncio 1.5.6 which is incompatible.\r\n",
      "sparkmagic 0.20.5 requires pandas<2.0.0,>=0.17.1, but you have pandas 2.0.3 which is incompatible.\u001b[0m\u001b[31m\r\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "!pip install pyarrow==8.0.0 pandas>=1.0.0 pyyaml==6.0.1 snowflake-connector-python==3.2.0 pytest pytest-sugar "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "1d758b70-e045-4566-91de-7c1ae6f10d57",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip -q install pyecharts absl-py imblearn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "71558801",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages/snowflake/connector/options.py:103: UserWarning: You have an incompatible version of 'pyarrow' installed (8.0.0), please install a version that adheres to: 'pyarrow<10.1.0,>=10.0.1; extra == \"pandas\"'\n",
      "  warn_incompatible_dep(\n",
      "Matplotlib is building the font cache; this may take a moment.\n",
      "DEBUG:absl:READY!!!\n"
     ]
    }
   ],
   "source": [
    "import snowflake.connector\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import pyecharts as echarts\n",
    "import os\n",
    "import boto3 \n",
    "import pickle\n",
    "import datetime\n",
    "from datetime import datetime, date\n",
    "from sklearn.preprocessing import StandardScaler, OrdinalEncoder\n",
    "# utils\n",
    "from getpass import getpass\n",
    "import numpy as np\n",
    "import seaborn as sns\n",
    "import random\n",
    "import data_prep \n",
    "import predictors\n",
    "import logging\n",
    "import time\n",
    "\n",
    "from imblearn.over_sampling import SMOTE\n",
    "from scipy.stats import pearsonr\n",
    "from sklearn.preprocessing import  OrdinalEncoder\n",
    "\n",
    "# logging and re\n",
    "from absl import logging\n",
    "import re\n",
    "\n",
    "\n",
    "log_level = \"DEBUG\"\n",
    "ticket_code = \"EXP_1\"\n",
    "\n",
    "logging.set_verbosity(log_level)\n",
    "logging.debug(\"READY!!!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "00d37ae4",
   "metadata": {},
   "outputs": [],
   "source": [
    "sec_id = 'dev/sagemaker-notebook-instance/SNOWFLAKE_PASSWORD'\n",
    "\n",
    "\n",
    "def get_secret_value(name, version=None):\n",
    "    \"\"\"Gets the value of a secret.\n",
    "\n",
    "    Version (if defined) is used to retrieve a particular version of\n",
    "    the secret.\n",
    "\n",
    "    \"\"\"\n",
    "    secrets_client = boto3.client(\"secretsmanager\")\n",
    "    kwargs = {'SecretId': name}\n",
    "    if version is not None:\n",
    "        kwargs['VersionStage'] = version\n",
    "    response = secrets_client.get_secret_value(**kwargs)\n",
    "    return response\n",
    "\n",
    "\n",
    "def get_snowflake_creds(username=\"SAGEMAKER\", account=\"orchard\",\n",
    "                        warehouse=\"DEV_OWS_ENGINEERING\"):\n",
    "    \"\"\"\n",
    "    Fetches and returns snowflake creds for connecting to snowflake\n",
    "\n",
    "    Please use this within the scope of a function if using this on a shared instance\n",
    "    This is so that the password is in memory only when its needed and gets dropped \n",
    "    once its no longer required.\n",
    "\n",
    "    returns:\n",
    "    - creds (dict) - a dictionary containing user creds\n",
    "\n",
    "    \"\"\"\n",
    "    creds = {\n",
    "      \"user\":  username,\n",
    "      \"password\": get_secret_value(sec_id)['SecretString'],\n",
    "      \"account\": \"orchard\",\n",
    "      \"warehouse\": warehouse,\n",
    "      \"protocol\": 'https'\n",
    "    }\n",
    "    return creds\n",
    "\n",
    "\n",
    "def snowflake_connector_factory(creds=None):\n",
    "    \"\"\"\n",
    "    A Factory for creating snowflake connectors.\n",
    "\n",
    "    This returns the cursor after opening a session with snowflake.\n",
    "\n",
    "    params:\n",
    "    - creds - snowflake credentials \n",
    "\n",
    "    returns:\n",
    "    - cursor - snowflake session cursor\n",
    "    \"\"\"\n",
    "    try:\n",
    "        if creds:\n",
    "            _creds = creds\n",
    "        else:\n",
    "            _creds = get_snowflake_creds()\n",
    "        return snowflake.connector.connect(**_creds).cursor()\n",
    "    except Exception as e:\n",
    "        logging.error(f\"Something went wrong - {str(e)}\")\n",
    "\n",
    "\n",
    "def _is_version_number(s):\n",
    "    \"Check and returns true if its a version number\"\n",
    "    return re.search(\"^[0-9][.0-9]*[0-9]$\", s) is not None\n",
    "\n",
    "\n",
    "def test_connection():\n",
    "    \"\"\" tests connection to snowflake \"\"\"\n",
    "    with snowflake_connector_factory() as cs:\n",
    "        try:\n",
    "            cs.execute(\"SELECT current_version()\")\n",
    "            one_row = cs.fetchone()\n",
    "            assert len(one_row) == 1\n",
    "            assert _is_version_number(one_row[0])\n",
    "            logging.info(f\"Your snowflake version - {one_row[0]} PASSED!\")\n",
    "        except Exception as e:\n",
    "          logging.error(f\"Something went wrong - {str(e)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3ffa745f",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:absl:Your snowflake version - 7.34.0 PASSED!\n"
     ]
    }
   ],
   "source": [
    "test_connection()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "55b94d75",
   "metadata": {},
   "outputs": [],
   "source": [
    "with snowflake_connector_factory() as cs:\n",
    "    try:\n",
    "        cs.execute(\"USE WAREHOUSE DEV_OWS_WAREHOUSE;\")\n",
    "        cs.execute(\"\"\"\n",
    "        \n",
    "        select * from intelligence.dev_zallard.project_maze_dataset;\n",
    "        \n",
    "        \"\"\")\n",
    "        rows = cs.fetchall()\n",
    "    except Exception as e:\n",
    "      logging.error(f\"Something went wrong - {str(e)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "8fe5749b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2918863, 23)\n",
      "(2918863, 23)\n"
     ]
    }
   ],
   "source": [
    "data_df = pd.DataFrame(rows, columns=map(lambda meta: meta[0], cs.description))\n",
    "original = data_df.drop_duplicates().copy()\n",
    "print(data_df.shape)\n",
    "print(original.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4aa6708c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc23f372",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d9c95f36-70f3-4ef2-978d-582ce6d4e42c",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = original.copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "19f3bb50-508f-4f67-8870-df907a2c9232",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 2918863 entries, 0 to 2918862\n",
      "Data columns (total 23 columns):\n",
      " #   Column               Dtype  \n",
      "---  ------               -----  \n",
      " 0   ARTIST_NAME          object \n",
      " 1   MIN_RELEASE_DATE     object \n",
      " 2   FIXED_RELEASE_DATE   object \n",
      " 3   ISRC                 object \n",
      " 4   MIN_CHART_DATE       object \n",
      " 5   DAYS_TO_CHART        float64\n",
      " 6   HIT                  int64  \n",
      " 7   PREVIOUS_HIT         int64  \n",
      " 8   DAYS_SINCE_LAST_HIT  float64\n",
      " 9   LATEST_HIT_DATE      object \n",
      " 10  ACOUSTICNESS         float64\n",
      " 11  DANCEABILITY         float64\n",
      " 12  DURATION_MS          int64  \n",
      " 13  ENERGY               float64\n",
      " 14  INSTRUMENTALNESS     float64\n",
      " 15  KEY                  int64  \n",
      " 16  LIVENESS             float64\n",
      " 17  LOUDNESS             float64\n",
      " 18  MODE                 int64  \n",
      " 19  SPEECHINESS          float64\n",
      " 20  TEMPO                float64\n",
      " 21  TIME_SIGNATURE       int64  \n",
      " 22  VALENCE              float64\n",
      "dtypes: float64(11), int64(6), object(6)\n",
      "memory usage: 512.2+ MB\n"
     ]
    }
   ],
   "source": [
    "df.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57f68e4a-c27e-4283-8262-a43b336e1aee",
   "metadata": {},
   "source": [
    "# Data Manipulation\n",
    "\n",
    "## Removing Oddities\n",
    "\n",
    "Removing some tracks where same ISRC is associated to multiple artist names.\n",
    "I haven't had chance to investigate this further, but simply decided to remove them for now."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "7a03a2a1-8808-4205-a2d0-c1e3cbc9c838",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2896730\n",
      "273606\n"
     ]
    }
   ],
   "source": [
    "print(df['ISRC'].nunique())\n",
    "print(df['ARTIST_NAME'].nunique())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "301f082f-70c1-4fc3-9f13-1e6345bad15c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "19528\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "19528"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ids=pd.DataFrame(original.groupby('ISRC')['ARTIST_NAME'].count()).reset_index()\n",
    "print(len(ids[ids['ARTIST_NAME']>1]))\n",
    "oddities = ids[ids['ARTIST_NAME']>1]['ISRC'].unique().tolist()\n",
    "len(oddities)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "649f01be-6015-4276-aaf5-eea4ca49a55a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2877202, 23)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = df[~df['ISRC'].isin(oddities)]\n",
    "df.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fd71caa-9f79-4f5a-afb5-a6f8cf24e37b",
   "metadata": {},
   "source": [
    "## Country specific analysis\n",
    "\n",
    "As the aim of this piece of analysis is to predict whether a track will reach Spotify Top 200 (USA), \n",
    "it makes no sense to include tracks from other markets. The solution below might be simplistic: \n",
    "from the ISRC, I'm deriving the country associated to a track by extracting the ISRC's prefix as per  \n",
    "https://isrc.ifpi.org/downloads/Valid_Characters.pdf\n",
    "\n",
    "I think US/Canada/Uk could all serve as training for a US chart. However, this should be cross-checked with \n",
    "substantive knowledge. For now I'm operating on a simpler assumption: \n",
    "**US track --> US chart**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "06ea0113-0495-4800-91f1-d0b95bf4387e",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "df['ISRC_first_two_characters'] = df['ISRC'].str[:2]\n",
    "\n",
    "conditions = [(df['ISRC_first_two_characters']=='AR'),\n",
    "              (df['ISRC_first_two_characters']=='AU'),\n",
    "              (df['ISRC_first_two_characters']=='AT'),\n",
    "              (df['ISRC_first_two_characters']=='BY'),\n",
    "              (df['ISRC_first_two_characters']=='BE'),\n",
    "              (df['ISRC_first_two_characters']=='BO'),\n",
    "              (df['ISRC_first_two_characters'].isin(['BR', 'BP', 'BX', 'BC', 'BK'])),\n",
    "              (df['ISRC_first_two_characters'].isin(['CA', 'CB'])),\n",
    "              (df['ISRC_first_two_characters']=='CL'),\n",
    "              (df['ISRC_first_two_characters']=='CO'),\n",
    "              (df['ISRC_first_two_characters']=='CY'),\n",
    "              (df['ISRC_first_two_characters']=='CY'),\n",
    "              (df['ISRC_first_two_characters']=='CZ'),\n",
    "              (df['ISRC_first_two_characters'].isin(['DK', 'GL', 'FO'])),\n",
    "              (df['ISRC_first_two_characters']=='DO'),\n",
    "              (df['ISRC_first_two_characters']=='EC'),\n",
    "              (df['ISRC_first_two_characters']=='EG'),\n",
    "              (df['ISRC_first_two_characters']=='SV'),\n",
    "              (df['ISRC_first_two_characters']=='EE'),\n",
    "              (df['ISRC_first_two_characters']=='FI'),\n",
    "              (df['ISRC_first_two_characters'].isin(['FR', 'FX'])),\n",
    "              (df['ISRC_first_two_characters']=='DE'),\n",
    "              (df['ISRC_first_two_characters']=='GR'),\n",
    "              (df['ISRC_first_two_characters']=='GT'),\n",
    "              (df['ISRC_first_two_characters']=='HN'),\n",
    "              (df['ISRC_first_two_characters']=='HK'),\n",
    "              (df['ISRC_first_two_characters']=='HU'),\n",
    "              (df['ISRC_first_two_characters']=='IS'),\n",
    "              (df['ISRC_first_two_characters']=='IN'),\n",
    "              (df['ISRC_first_two_characters']=='ID'),\n",
    "              (df['ISRC_first_two_characters']=='IE'),\n",
    "              (df['ISRC_first_two_characters']=='IL'),\n",
    "              (df['ISRC_first_two_characters']=='IT'),\n",
    "              (df['ISRC_first_two_characters']=='JP'),\n",
    "              (df['ISRC_first_two_characters']=='KZ'),\n",
    "              (df['ISRC_first_two_characters']=='LV'),\n",
    "              (df['ISRC_first_two_characters']=='LT'),\n",
    "              (df['ISRC_first_two_characters']=='LU'),\n",
    "              (df['ISRC_first_two_characters']=='MY'),\n",
    "              (df['ISRC_first_two_characters']=='MX'),\n",
    "              (df['ISRC_first_two_characters']=='MA'),\n",
    "              (df['ISRC_first_two_characters']=='NL'),\n",
    "              (df['ISRC_first_two_characters']=='NZ'),\n",
    "              (df['ISRC_first_two_characters']=='NG'),\n",
    "              (df['ISRC_first_two_characters']=='NO'),\n",
    "              (df['ISRC_first_two_characters']=='PK'),\n",
    "              (df['ISRC_first_two_characters']=='PA'),\n",
    "              (df['ISRC_first_two_characters']=='PY'),\n",
    "              (df['ISRC_first_two_characters']=='PE'),\n",
    "              (df['ISRC_first_two_characters']=='PH'),\n",
    "              (df['ISRC_first_two_characters']=='PL'),\n",
    "              (df['ISRC_first_two_characters']=='PT'),\n",
    "              (df['ISRC_first_two_characters']=='RO'),\n",
    "              (df['ISRC_first_two_characters']=='SA'),\n",
    "              (df['ISRC_first_two_characters']=='SG'),\n",
    "              (df['ISRC_first_two_characters']=='SK'),\n",
    "              (df['ISRC_first_two_characters'].isin(['ZA', 'ZB'])),\n",
    "              (df['ISRC_first_two_characters']=='ES'),\n",
    "              (df['ISRC_first_two_characters']=='SE'),\n",
    "              (df['ISRC_first_two_characters']=='CH'),\n",
    "              (df['ISRC_first_two_characters']=='TH'),\n",
    "              (df['ISRC_first_two_characters']=='TR'),\n",
    "              (df['ISRC_first_two_characters']=='AE'),\n",
    "              (df['ISRC_first_two_characters']=='UA'),\n",
    "              (df['ISRC_first_two_characters'].isin(['UK', 'GX', 'GB'])),\n",
    "              (df['ISRC_first_two_characters']=='UY'),\n",
    "              (df['ISRC_first_two_characters'].isin(['US', 'QM', 'QZ'])),\n",
    "              (df['ISRC_first_two_characters']=='VE'),\n",
    "              (df['ISRC_first_two_characters']=='VN'),\n",
    "              (df['ISRC_first_two_characters'].isin(['PK', 'TC', 'CN', 'ZZ', 'TW', 'BB', 'BG', 'RU', 'KR', 'LK', 'DG', 'SI', 'YE', 'BH', 'JM', 'GD', 'WZ', 'NP', 'SF', 'AI', 'CU']))\n",
    "             ]\n",
    "\n",
    "choices = ['Argentina','Australia','Austria', 'Belarus', 'Belgium', 'Bolivia', 'Brazil', 'Bulgaria', 'Canada', 'Chile', 'Colombia', 'Cyprus', 'Czech_Republic', 'Denmark',\n",
    "           'Dominican_Republic', 'Ecuador', 'Egypt', 'El_Salvador', 'Estonia', 'Finland', 'France', 'Germany', 'Greece', 'Guatemala', 'Honduras', 'Hong_Kong', 'Hungary',\n",
    "           'Iceland', 'India', 'Indonesia', 'Ireland', 'Israel', 'Italy', 'Japan', 'Kazakhstan', 'Latvia', 'Lithuania', 'Luxembourg', 'Malaysia', 'Mexico', 'Morocco',\n",
    "           'Netherlands', 'New_Zealand', 'Nigeria', 'Norway', 'Pakistan', 'Panama', 'Paraguay', 'Peru', 'Philippines', 'Poland', 'Portugal', 'Romania', 'Saudi_Arabia', \n",
    "           'Singapore', 'Slovakia', 'South_Africa', 'Spain', 'Sweden', 'Switzerland', 'Thailand', 'Turkey', 'UAE', 'Ukraine', 'United_Kingdom', 'Uruguay', 'USA', 'Venezuela',\n",
    "           'Vietnam', 'Worldwild/Other']\n",
    "\n",
    "\n",
    "df['Market_manually_derived'] = np.select(conditions, choices)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e56e8a68-b405-4b21-83d1-e05bcfe57eea",
   "metadata": {},
   "source": [
    "## Fixing dates "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "54cdd6c2-2e38-48a1-8425-b684f11a05f8",
   "metadata": {},
   "outputs": [],
   "source": [
    "df['FIXED_RELEASE_DATE'] = pd.to_datetime(df['FIXED_RELEASE_DATE'])\n",
    "df['MIN_CHART_DATE'] = pd.to_datetime(df['MIN_CHART_DATE'])\n",
    "df['LATEST_HIT_DATE'] = pd.to_datetime(df['LATEST_HIT_DATE'])\n",
    "df['Month_release'] = df['FIXED_RELEASE_DATE'].dt.month_name()\n",
    "df['Month_chart'] = df['MIN_CHART_DATE'].dt.month_name()\n",
    "df['Month_latest_chart'] = df['LATEST_HIT_DATE'].dt.month_name()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34ed5a05-1453-401e-b895-9e1d6246f6f5",
   "metadata": {},
   "source": [
    "## Creating artist score variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "7fe79ea4-66b2-4d51-83b4-3b4ac3d54c08",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_12735/1478880652.py:3: UserWarning: \n",
      "\n",
      "`distplot` is a deprecated function and will be removed in seaborn v0.14.0.\n",
      "\n",
      "Please adapt your code to use either `displot` (a figure-level function with\n",
      "similar flexibility) or `histplot` (an axes-level function for histograms).\n",
      "\n",
      "For a guide to updating your code to use the new functions, please see\n",
      "https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751\n",
      "\n",
      "  sns.distplot(df['DAYS_SINCE_LAST_HIT'])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Axes: xlabel='DAYS_SINCE_LAST_HIT', ylabel='Density'>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlIAAAGwCAYAAABiu4tnAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABeDElEQVR4nO3dfVxUZf4//tfcwAwgjCjCDIqIKCqRpmAIhXetCJYr6RarRbq7ubLdItsvU7Nadzey3az14021eZPfStlNMXdDV0xFzdFEEVHxJkVBZERQGO5vZs7vj5HJiRvhCB5uXs/HY1Y5c51z3ueMNK+9znWuIxMEQQARERERtZpc6gKIiIiIOisGKSIiIiKRGKSIiIiIRGKQIiIiIhKJQYqIiIhIJAYpIiIiIpEYpIiIiIhEUkpdQFdmNptx7do1ODs7QyaTSV0OERERtYAgCCgtLYWnpyfk8ub7nBik2tG1a9fg5eUldRlEREQkQm5uLvr169dsGwapduTs7AzA8kG4uLhIXA0RERG1hNFohJeXl/V7vDkMUu2o/nKei4sLgxQREVEn05JhORxsTkRERCQSgxQRERGRSAxSRERERCIxSBERERGJxCBFREREJBKDFBEREZFIDFJEREREIjFIEREREYnEIEVEREQkEoMUERERkUgMUkREREQiMUgRERERicQgRURERCQSgxQRERGRSAxSRERERCIppS6AuoevjuS0qv2s4P7tVAkREVHbYY8UERERkUgMUkREREQiMUgRERERicQgRURERCQSgxQRERGRSAxSRERERCIxSBERERGJxCBFREREJBKDFBEREZFIDFJEREREIjFIEREREYkkeZBavXo1fHx8oFarERgYiAMHDjTbPjU1FYGBgVCr1Rg4cCA+/vjjBm22bNkCf39/qFQq+Pv7Iykpyeb9NWvWYPjw4XBxcYGLiwtCQkKwY8cOmzZz5syBTCazeY0ZM+beD5iIiIi6DEmDVGJiIuLi4rB48WKkp6cjLCwMkZGRyMlp/AG32dnZmDJlCsLCwpCeno5FixbhlVdewZYtW6xt9Ho9oqOjERMTg4yMDMTExODpp5/GkSNHrG369euH9957D2lpaUhLS8PEiRMxbdo0nD592mZ/ERERyM/Pt76Sk5Pb50QQERFRpyQTBEGQaufBwcEYNWoU1qxZY102bNgwREVFISEh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KaXasZubGxQKRYMenoKCggY9QfW0Wm2j7ZVKJXr37t1sm59v097eHoMGDQIABAUF4ejRo/jHP/6BTz75BFqtFoClZ0qn07WoNsBy+U+lUjV32ERERNSFSNYjZW9vj8DAQKSkpNgsT0lJQWhoaKPrhISENGi/a9cuBAUFwc7Ortk2TW2zniAIqK6uBgD4+PhAq9XabKempgapqal33Q4RERF1H5L1SAFAfHw8YmJiEBQUhJCQEHz66afIyclBbGwsAMulsry8PGzcuBGA5Q69lStXIj4+HnPnzoVer8fatWtt7sZ79dVXMXbsWCxbtgzTpk3DN998g927d+PgwYPWNosWLUJkZCS8vLxQWlqKzZs3Y9++fdi5cycAyyW9uLg4vPvuuxg8eDAGDx6Md999F46Ojpg1a9Z9PENERETUkUkapKKjo1FUVISlS5ciPz8fAQEBSE5Ohre3NwAgPz/fZk4pHx8fJCcnY/78+Vi1ahU8PT2xYsUKzJgxw9omNDQUmzdvxptvvoklS5bA19cXiYmJCA4Otra5fv06YmJikJ+fD41Gg+HDh2Pnzp2YNGmStc3rr7+OyspKvPDCC7h16xaCg4Oxa9cuODs734czQ0RERJ2BpPNIdXWcR+onnEeKiIg6i04xjxQRERFRZ8cgRURERCQSgxQRERGRSAxSRERERCIxSBERERGJxCBFREREJBKDFBEREZFIDFJEREREIjFIEREREYnEIEVEREQkEoMUERERkUgMUkREREQiMUgRERERicQgRURERCQSgxQRERGRSAxSRERERCIxSBERERGJxCBFREREJBKDFBEREZFIDFJEREREIjFIEREREYnEIEVEREQkEoMUERERkUgMUkREREQiMUgRERERicQgRURERCQSgxQRERGRSAxSRERERCIxSBERERGJxCBFREREJBKDFBEREZFIDFJEREREIjFIEREREYnEIEVEREQkEoMUERERkUgMUkREREQiMUgRERERiSR5kFq9ejV8fHygVqsRGBiIAwcONNs+NTUVgYGBUKvVGDhwID7++OMGbbZs2QJ/f3+oVCr4+/sjKSnJ5v2EhASMHj0azs7OcHd3R1RUFM6dO2fTZs6cOZDJZDavMWPG3PsBExERUZchaZBKTExEXFwcFi9ejPT0dISFhSEyMhI5OTmNts/OzsaUKVMQFhaG9PR0LFq0CK+88gq2bNlibaPX6xEdHY2YmBhkZGQgJiYGTz/9NI4cOWJtk5qaihdffBGHDx9GSkoK6urqEB4ejvLycpv9RUREID8/3/pKTk5unxNBREREnZJMEARBqp0HBwdj1KhRWLNmjXXZsGHDEBUVhYSEhAbtFyxYgO3btyMrK8u6LDY2FhkZGdDr9QCA6OhoGI1G7Nixw9omIiICrq6u2LRpU6N13LhxA+7u7khNTcXYsWMBWHqkiouLsW3bNtHHZzQaodFoUFJSAhcXF9Hb6Qq+OtJ4OG7KrOD+7VQJERFR81rz/S1Zj1RNTQ2OHTuG8PBwm+Xh4eE4dOhQo+vo9foG7SdPnoy0tDTU1tY226apbQJASUkJAKBXr142y/ft2wd3d3f4+flh7ty5KCgoaPaYqqurYTQabV5ERETUdUkWpAoLC2EymeDh4WGz3MPDAwaDodF1DAZDo+3r6upQWFjYbJumtikIAuLj4/Hoo48iICDAujwyMhJffvkl9uzZgw8++ABHjx7FxIkTUV1d3eQxJSQkQKPRWF9eXl5NnwAiIiLq9JRSFyCTyWx+FgShwbK7tf/58tZs86WXXsLJkydx8OBBm+XR0dHWvwcEBCAoKAje3t749ttvMX369Ea3tXDhQsTHx1t/NhqNDFNERERdmGRBys3NDQqFokFPUUFBQYMepXparbbR9kqlEr179262TWPbfPnll7F9+3bs378f/fr1a7ZenU4Hb29vXLhwock2KpUKKpWq2e0QERFR1yHZpT17e3sEBgYiJSXFZnlKSgpCQ0MbXSckJKRB+127diEoKAh2dnbNtrlzm4Ig4KWXXsLWrVuxZ88e+Pj43LXeoqIi5ObmQqfTtej4iIiIqOuTdPqD+Ph4fPbZZ1i3bh2ysrIwf/585OTkIDY2FoDlUtlzzz1nbR8bG4srV64gPj4eWVlZWLduHdauXYvXXnvN2ubVV1/Frl27sGzZMpw9exbLli3D7t27ERcXZ23z4osv4osvvsBXX30FZ2dnGAwGGAwGVFZWAgDKysrw2muvQa/X4/Lly9i3bx+mTp0KNzc3PPnkk/fn5BAREVGHJ+kYqejoaBQVFWHp0qXIz89HQEAAkpOT4e3tDQDIz8+3mVPKx8cHycnJmD9/PlatWgVPT0+sWLECM2bMsLYJDQ3F5s2b8eabb2LJkiXw9fVFYmIigoODrW3qp1sYP368TT3r16/HnDlzoFAokJmZiY0bN6K4uBg6nQ4TJkxAYmIinJ2d2/GMEBERUWci6TxSXR3nkfoJ55EiIqLOolPMI0VERETU2TFIEREREYnEIEVEREQkEoMUERERkUgMUkREREQiMUgRERERicQgRURERCQSgxQRERGRSAxSRERERCIxSBERERGJxCBFREREJBKDFBEREZFIDFJEREREIjFIEREREYnEIEVEREQkEoMUERERkUgMUkREREQiMUgRERERicQgRURERCQSgxQRERGRSAxSRERERCIxSBERERGJxCBFREREJBKDFBEREZFIDFJEREREIokKUtnZ2W1dBxEREVGnIypIDRo0CBMmTMAXX3yBqqqqtq6JiIiIqFMQFaQyMjIwcuRI/PGPf4RWq8W8efPwww8/tHVtRERERB2aqCAVEBCA5cuXIy8vD+vXr4fBYMCjjz6KBx54AMuXL8eNGzfauk4iIiKiDueeBpsrlUo8+eST+Ne//oVly5bh4sWLeO2119CvXz8899xzyM/Pb6s6iYiIiDqcewpSaWlpeOGFF6DT6bB8+XK89tpruHjxIvbs2YO8vDxMmzatreokIiIi6nCUYlZavnw51q9fj3PnzmHKlCnYuHEjpkyZArnckst8fHzwySefYOjQoW1aLBEREVFHIipIrVmzBr/97W/xm9/8BlqtttE2/fv3x9q1a++pOCIiIqKOTFSQSklJQf/+/a09UPUEQUBubi769+8Pe3t7zJ49u02KJCIiIuqIRI2R8vX1RWFhYYPlN2/ehI+Pzz0XRURERNQZiApSgiA0urysrAxqtfqeCiIiIiLqLFp1aS8+Ph4AIJPJ8NZbb8HR0dH6nslkwpEjR/DQQw+1aYFEREREHVWreqTS09ORnp4OQRCQmZlp/Tk9PR1nz57FiBEjsGHDhlYVsHr1avj4+ECtViMwMBAHDhxotn1qaioCAwOhVqsxcOBAfPzxxw3abNmyBf7+/lCpVPD390dSUpLN+wkJCRg9ejScnZ3h7u6OqKgonDt3zqaNIAh455134OnpCQcHB4wfPx6nT59u1bERERFR19aqILV3717s3bsXs2fPxo4dO6w/7927F//73//wySefYPDgwS3eXmJiIuLi4rB48WKkp6cjLCwMkZGRyMnJabR9dnY2pkyZgrCwMKSnp2PR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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Checking of distribution since last hit ahead of creating 'artist_score' variable\n",
    "\n",
    "sns.distplot(df['DAYS_SINCE_LAST_HIT'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "54ee65fd-589c-48fc-9941-22715dee8ef9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "count    1855.000000\n",
       "mean      324.987062\n",
       "std       331.419650\n",
       "min         1.000000\n",
       "25%        85.000000\n",
       "50%       225.000000\n",
       "75%       463.000000\n",
       "max      1863.000000\n",
       "Name: DAYS_SINCE_LAST_HIT, dtype: float64"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df['DAYS_SINCE_LAST_HIT'].describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "0742548f-860c-4711-a937-9300c3b545fb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Maybe setting cutoff for previous hit using one of those values\n",
    "\n",
    "# perc_75 = df['DAYS_SINCE_LAST_HIT'].describe()[6]\n",
    "# median = df['DAYS_SINCE_LAST_HIT'].describe()[5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "88e5ecc8-1af4-45ca-b0e3-882995dd7508",
   "metadata": {},
   "outputs": [],
   "source": [
    "conditions = [(df['PREVIOUS_HIT']==0),\n",
    "             (df['PREVIOUS_HIT']==1) & (df['DAYS_SINCE_LAST_HIT'] > 365),\n",
    "             (df['PREVIOUS_HIT']==1) & (df['DAYS_SINCE_LAST_HIT'] <= 365)]\n",
    "\n",
    "choices = ['no_previous_hit', 'non_recent_hit', 'recent_hit']\n",
    "\n",
    "df['artist_score'] = np.select(conditions, choices)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "31584e9c-583b-41ff-82f3-1900d022aefe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "artist_score\n",
       "no_previous_hit    2875347\n",
       "recent_hit            1262\n",
       "non_recent_hit         593\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df['artist_score'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "58fb72bf-5db3-46bc-80ff-9675a86f0229",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "HIT\n",
      "0    2876919\n",
      "1        283\n",
      "Name: count, dtype: int64\n",
      "PREVIOUS_HIT\n",
      "0    2875347\n",
      "1       1855\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "print(df['HIT'].value_counts())\n",
    "print(df['PREVIOUS_HIT'].value_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad7f12bf-81d6-44b5-bb0e-7adf48420aeb",
   "metadata": {},
   "source": [
    "## Checking for missing values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "d8bbe1da-6447-4153-a197-f61bd6cb2126",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Index: 2877202 entries, 0 to 2918862\n",
      "Data columns (total 29 columns):\n",
      " #   Column                     Dtype         \n",
      "---  ------                     -----         \n",
      " 0   ARTIST_NAME                object        \n",
      " 1   MIN_RELEASE_DATE           object        \n",
      " 2   FIXED_RELEASE_DATE         datetime64[ns]\n",
      " 3   ISRC                       object        \n",
      " 4   MIN_CHART_DATE             datetime64[ns]\n",
      " 5   DAYS_TO_CHART              float64       \n",
      " 6   HIT                        int64         \n",
      " 7   PREVIOUS_HIT               int64         \n",
      " 8   DAYS_SINCE_LAST_HIT        float64       \n",
      " 9   LATEST_HIT_DATE            datetime64[ns]\n",
      " 10  ACOUSTICNESS               float64       \n",
      " 11  DANCEABILITY               float64       \n",
      " 12  DURATION_MS                int64         \n",
      " 13  ENERGY                     float64       \n",
      " 14  INSTRUMENTALNESS           float64       \n",
      " 15  KEY                        int64         \n",
      " 16  LIVENESS                   float64       \n",
      " 17  LOUDNESS                   float64       \n",
      " 18  MODE                       int64         \n",
      " 19  SPEECHINESS                float64       \n",
      " 20  TEMPO                      float64       \n",
      " 21  TIME_SIGNATURE             int64         \n",
      " 22  VALENCE                    float64       \n",
      " 23  ISRC_first_two_characters  object        \n",
      " 24  Market_manually_derived    object        \n",
      " 25  Month_release              object        \n",
      " 26  Month_chart                object        \n",
      " 27  Month_latest_chart         object        \n",
      " 28  artist_score               object        \n",
      "dtypes: datetime64[ns](3), float64(11), int64(6), object(9)\n",
      "memory usage: 658.5+ MB\n"
     ]
    }
   ],
   "source": [
    "df.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "788a85f4-d01b-42fb-8a97-9af616a81c3f",
   "metadata": {},
   "source": [
    "## Encoding dictionaries\n",
    "\n",
    "To run, models need variables to be transformed. As I'll test the model on a real case, I wanted to extract the way the algorithms recode categorical variables, so that I can replicate these values on a small set of real values. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "a9003033-362c-4b17-8995-c8e7bfd2210a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{('no_previous_hit',): array([0.]), ('recent_hit',): array([2.]), ('non_recent_hit',): array([1.])}\n",
      "-----------------------------------\n",
      "-----------------------------------\n",
      "{('June',): array([6.]), ('February',): array([3.]), ('July',): array([5.]), ('March',): array([7.]), ('November',): array([9.]), ('April',): array([0.]), ('September',): array([11.]), ('December',): array([2.]), ('August',): array([1.]), ('October',): array([10.]), ('May',): array([8.]), ('January',): array([4.])}\n"
     ]
    }
   ],
   "source": [
    "encoding = df.copy()\n",
    "categorical_features1 = np.array(encoding[['artist_score']])\n",
    "label_encoder1 = OrdinalEncoder()\n",
    "encoded1 = label_encoder1.fit_transform(categorical_features1)\n",
    "#X_categorical1 = pd.DataFrame(encoded1, columns = categorical_features1.columns) \n",
    "    \n",
    "encoded_dict1 = {}\n",
    "for i, value in enumerate(categorical_features1):\n",
    "    encoded_dict1[tuple(value)] = encoded1[i]\n",
    "    \n",
    "categorical_features2 = np.array(encoding[['Month_release']])\n",
    "label_encoder2 = OrdinalEncoder()\n",
    "encoded2 = label_encoder2.fit_transform(categorical_features2)\n",
    "encoded_dict2 = {}\n",
    "for i, value in enumerate(categorical_features2):\n",
    "    encoded_dict2[tuple(value)] = encoded2[i]   \n",
    "\n",
    "print(encoded_dict1)\n",
    "print('-----------------------------------')\n",
    "print('-----------------------------------')\n",
    "print(encoded_dict2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69fa8aea-7367-4e58-be9b-c5d9d8584711",
   "metadata": {},
   "source": [
    "# Modelling\n",
    "\n",
    "## Options\n",
    "\n",
    "1. Work on a small (yet balanced)subset: we create 2 balanced groups of labels 0 and 1. \n",
    "   sample_size = 283 indicates that we match 0s to be the same as 1s\n",
    "\n",
    "2. Use SMOTE to bring 1s to the same size as 0s\n",
    "   \n",
    "3. Work with unbalanced data:  we can use cost-sensitive learning by assigning higher misclassification costs to the 1s. This requires changing in the predictors.py file. The dataset remains untouched.\n",
    "\n",
    "4. Mixed of option 1 and 2: randomly select a sample of 0s (e.g n = 10000), then use SMOTE to bring 1s to the same size\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8cf91c44-e810-45ca-b3a0-25c2b289b1ef",
   "metadata": {},
   "source": [
    "## Subsetting by US tracks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "e384b5d9-2c6a-45e4-be44-e5c92c1cefae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1412606, 29)"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "usa = df[df['Market_manually_derived']=='USA']\n",
    "usa.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "8607f76c-afb6-4ea2-a48f-9283e11f65d3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "HIT\n",
       "0    1412368\n",
       "1        238\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "usa['HIT'].value_counts()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4df95be9-e765-4c62-94ef-e3091b3e6fcd",
   "metadata": {},
   "source": [
    "### OPTION 1: Working on very small (yet balanced) subset\n",
    "\n",
    "(NB: comment the other options)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "1d5d2ebf-b856-4fb8-a051-9da3a8ae1b2a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# subset_hit0_list = usa[usa['HIT']==0]['ISRC'].unique().tolist()\n",
    "# sample_size = 238 \n",
    "# random.seed(2023)\n",
    "# random_sample = random.sample(subset_hit0_list, k=sample_size)\n",
    "# manually_balanced_data = usa[(usa['HIT']==1) | (usa['ISRC'].isin(random_sample))].copy()\n",
    "# manually_balanced_data.shape\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d113b36e-dc2d-4967-b6cb-a71b252accf9",
   "metadata": {},
   "source": [
    "#### Cross Validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "13da2280-2c4e-4804-8ecb-f4a8c5fc7d64",
   "metadata": {},
   "outputs": [],
   "source": [
    "# (X_prepared, y_prepared) = data_prep.prepare_data(manually_balanced_data)\n",
    "\n",
    "# (X_train, y_train, X_test, y_test) = data_prep.split_train_test_data(X_prepared, y_prepared)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd58e8ce-9290-4ef8-9ba5-24d8866a72b4",
   "metadata": {},
   "source": [
    "### OPTION 2: Over Sampling\n",
    "\n",
    "(NB: comment the other options)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "379a2a30-b806-4402-9c90-9321ff381825",
   "metadata": {},
   "source": [
    "\n",
    "---------------------------------------------------------------------------------------------------------\n",
    "From: https://machinelearningmastery.com/smote-oversampling-for-imbalanced-classification/\n",
    "\n",
    "**SMOTE (*Synthetic Minority Oversampling Technique*):**\n",
    "\n",
    "This technique was described by Nitesh Chawla, et al. in their 2002 paper named for the technique titled “SMOTE: Synthetic Minority Over-sampling Technique.”\n",
    "\n",
    "SMOTE works by selecting examples that are close in the feature space, drawing a line between the examples in the feature space and drawing a new sample at a point along that line.\n",
    "\n",
    "Specifically, a random example from the minority class is first chosen. Then k of the nearest neighbors for that example are found (typically k=5). A randomly selected neighbor is chosen and a synthetic example is created at a randomly selected point between the two examples in feature space.\n",
    "\n",
    "    … SMOTE first selects a minority class instance a at random and finds its k nearest minority class neighbors. The synthetic instance is then created by choosing one of the k nearest neighbors b at random and connecting a and b to form a line segment in the feature space. The synthetic instances are generated as a convex combination of the two chosen instances a and b.\n",
    "\n",
    "— Page 47, Imbalanced Learning: Foundations, Algorithms, and Applications, 2013.\n",
    "\n",
    "This procedure can be used to create as many synthetic examples for the minority class as are required. As described in the paper, it suggests first using random undersampling to trim the number of examples in the majority class, then use SMOTE to oversample the minority class to balance the class distribution.\n",
    "\n",
    "    The combination of SMOTE and under-sampling performs better than plain under-sampling.\n",
    "\n",
    "— SMOTE: Synthetic Minority Over-sampling Technique, 2011.\n",
    "\n",
    "The approach is effective because new synthetic examples from the minority class are created that are plausible, that is, are relatively close in feature space to existing examples from the minority class.\n",
    "\n",
    "    Our method of synthetic over-sampling works to cause the classifier to build larger decision regions that contain nearby minority class points.\n",
    "\n",
    "— SMOTE: Synthetic Minority Over-sampling Technique, 2011.\n",
    "\n",
    "A general downside of the approach is that synthetic examples are created without considering the majority class, possibly resulting in ambiguous examples if there is a strong overlap for the classes.\n",
    "\n",
    "---------------------------------------------------------------------------------------------------------\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "c949963c-4531-4e5a-a48c-cd643f9de8bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "#(X_prepared, y_prepared) = data_prep.prepare_data(usa)\n",
    "\n",
    "#X_resampled, y_resampled = SMOTE(random_state=0, sampling_strategy='minority').fit_resample(X_prepared, y_prepared)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "583b152e-e58e-4057-8b92-39b266a44581",
   "metadata": {},
   "source": [
    "#### Cross Validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "ce9dbe05-ff08-46bf-a22c-5756e67e4b72",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "#(X_train, y_train, X_test, y_test) = data_prep.split_train_test_data(X_resampled, y_resampled)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7fc154ee-7679-4cf4-b898-059970db3387",
   "metadata": {},
   "source": [
    "### OPTION 3: Working with unchanged dataset, but using a cost-sensitive learning\n",
    "\n",
    "(NB: change predictors.py script where indicated and comment the other options)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8bbc7f93-7886-42db-ab4d-9674ba98bd50",
   "metadata": {},
   "source": [
    "#### Cross Validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "bd31a34d-2f8b-40ee-a14f-caddc1006108",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "(X_prepared, y_prepared) = data_prep.prepare_data(usa)\n",
    "\n",
    "(X_train, y_train, X_test, y_test) = data_prep.split_train_test_data(X_prepared, y_prepared)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5601d0c5-59f5-481a-9eb2-7644979e51d3",
   "metadata": {},
   "source": [
    "### OPTION 4: Mixed of options 1 and 2\n",
    "\n",
    "(NB: change back predictors.py script where indicated and comment the other options)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "de484796-5a6b-4bb2-b4dd-cde53e80a8da",
   "metadata": {},
   "outputs": [],
   "source": [
    "# subset_hit0_list = usa[usa['HIT']==0]['ISRC'].unique().tolist()\n",
    "# sample_size = 10000 \n",
    "# random.seed(2023)\n",
    "# random_sample = random.sample(subset_hit0_list, k=sample_size)\n",
    "# manually_balanced_data = usa[(usa['HIT']==1) | (usa['ISRC'].isin(random_sample))].copy()\n",
    "\n",
    "#(X_prepared, y_prepared) = data_prep.prepare_data(manually_balanced_data)\n",
    "\n",
    "#X_resampled, y_resampled = SMOTE(random_state=0, sampling_strategy='minority').fit_resample(X_prepared, y_prepared)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b951013-1308-48df-90cf-59671e0a9170",
   "metadata": {},
   "source": [
    "#### Cross Validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "d8ebd4bb-19eb-4b12-9651-12bf752b232f",
   "metadata": {},
   "outputs": [],
   "source": [
    "#(X_train, y_train, X_test, y_test) = data_prep.split_train_test_data(X_resampled, y_resampled)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48c9ebe9-a237-4bd8-b122-046e14007dfc",
   "metadata": {},
   "source": [
    "#### Checking Response Variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "0e04867e-a355-4f5c-96bf-a79719fe31b8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "HIT\n",
       "0    988657\n",
       "1       167\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train['HIT'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "5a768aa3-51e9-4772-b12a-61f2432fcd63",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "HIT\n",
       "0    423711\n",
       "1        71\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_test['HIT'].value_counts()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf24a904-b3df-4d3c-b52d-c0b9a7d27f77",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Logistic Regression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "8f69a56b-31aa-4eab-8ffd-445072d0fab8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# log_model = predictors.LogisticRegressionModel(X_train, y_train)\n",
    "# log_model.train()\n",
    "# log_performances = predictors.estimate_predictor(log_model, X_test, y_test)\n",
    "# log_performances"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "c176266e-1a6f-4095-b1c9-a70185fd31ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "# macro_recall = log_performances['macro avg']['recall']\n",
    "# macro_recall"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "7fe1cf1e-6a4e-4ec3-8d57-cd74164982c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "#print(log_model.model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "2713f4f8-5d41-4ba0-b62d-77eb3cabed1f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# matrix_log = predictors.confusion_matrix_calculation(log_model, X_test, y_test)\n",
    "# print(matrix_log)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "759b7a2c-1b68-42fd-9110-af53c6128992",
   "metadata": {},
   "outputs": [],
   "source": [
    "#log_model.important_features()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "868047c8-732d-4bf8-9517-345dc8baafd1",
   "metadata": {},
   "outputs": [],
   "source": [
    "#log_model.model_coefficients()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "521813d7-535e-41fa-99d1-4787e5121f91",
   "metadata": {},
   "outputs": [],
   "source": [
    "#log_model.model_intercept()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92f40d5a-362e-44de-a776-353ce9637f06",
   "metadata": {},
   "source": [
    "# Bootstrapping Logistic regression\n",
    "\n",
    "This is to use in options 1 and 4: as effectively, I've changed the distribution of the response and then extracted a random samples, I decided to check if I kept getting consistent results using different random samples of class 0. I plotted *Accuracy* and *Recall* to check the variability of these distributions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "82b072e2-8cd5-4c13-adf9-15e85ab3b313",
   "metadata": {},
   "outputs": [],
   "source": [
    "# from sklearn.metrics import accuracy_score\n",
    "\n",
    "# accuracy  = []\n",
    "# recall = []\n",
    "# n_iterations = 1000\n",
    "\n",
    "# for i in range(n_iterations):\n",
    "    \n",
    "#     subset_hit0_list_boot = usa[usa['HIT']==0]['ISRC'].unique().tolist()\n",
    "#     sample_size_boot = 10000\n",
    "#     random_sample_boot = random.sample(subset_hit0_list_boot, k=sample_size_boot)\n",
    "#     data_boot = usa[(usa['HIT']==1) | (usa['ISRC'].isin(random_sample_boot))].copy()\n",
    "#     (X_prepared_boot, y_prepared_boot) = data_prep.prepare_data(data_boot)\n",
    "#     (X_train_boot, y_train_boot, X_test_boot, y_test_boot) = data_prep.split_train_test_data(X_prepared_boot, y_prepared_boot)\n",
    "#     log_model_boot = predictors.LogisticRegressionModel(X_train_boot, y_train_boot)\n",
    "#     log_model_boot.train()\n",
    "#     log_performances_boot = predictors.estimate_predictor(log_model_boot, X_test_boot, y_test_boot)\n",
    "#     score = predictors.accuracy_calculator(log_model_boot, X_test_boot, y_test_boot)\n",
    "#     macro_recall = log_performances_boot['macro avg']['recall']\n",
    "#     accuracy.append(score)\n",
    "#     recall.append(macro_recall)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "ffaebbec-3b6b-4396-b26a-311e9b172de0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# sns.kdeplot(accuracy)\n",
    "# plt.title('Accuracy across 1000 bootstrap samples')\n",
    "# plt.xlabel('Accuracy')\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "79a2049b-b0f8-43d6-8be5-a043d7c8b1e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# sns.kdeplot(recall)\n",
    "# plt.title('Recall across 1000 bootstrap samples')\n",
    "# plt.xlabel('Recall')\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74c4f692-cebc-45f6-b69f-a5bee075525d",
   "metadata": {},
   "source": [
    "# Random Forest "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aeac72c6-119a-46de-9ac1-5a75b0c5157d",
   "metadata": {},
   "outputs": [],
   "source": [
    "rf_model = predictors.RandomForestModel(X_train, y_train)\n",
    "rf_model.train()\n",
    "rf_performances = predictors.estimate_predictor(rf_model, X_test, y_test)\n",
    "print(rf_performances)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "09165690-431d-44ed-ade5-3078a369745d",
   "metadata": {},
   "outputs": [],
   "source": [
    "matrix_rf = predictors.confusion_matrix_calculation(rf_model, X_test, y_test)\n",
    "print(matrix_rf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "981c3c8a-2300-42ef-975f-b1d6f4a7464c",
   "metadata": {},
   "outputs": [],
   "source": [
    "rf_model.important_features()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09e86740-2098-44b4-8bae-06282ef114ae",
   "metadata": {},
   "source": [
    "# Pickling the model\n",
    "\n",
    "This is for real life testing: I saved the model and call it back just to test on new data.\n",
    "This saves time as training of the model is no longer needed. \n",
    "Here, I'm retesting it works."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21f2bdbf-05c6-46b9-b189-13f6c8fde4e7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "import datetime\n",
    "\n",
    "# with open('/Users/impr001/Documents/Jupyter_Notebooks/Maze/log_model_6_sept_2023.pkl', 'wb') as file:\n",
    "#        pickle.dump(log_model, file)\n",
    "\n",
    "# pickled_model = pickle.dump(log_model)\n",
    "# s3 = boto3.client('s3')\n",
    "# bucket_name = 'dev-cucumbers'\n",
    "# filepath = \"eimpara/Maze/log_model_27_sept_2023.pkl\"\n",
    "# s3.put_object(Body=pickled_model, Bucket=bucket_name, Key=filepath)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a0e7e209-c32a-4da4-be42-d64193869fd2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# with open('/Users/impr001/Documents/Jupyter_Notebooks/Maze/log_model_6_sept_2023.pkl', 'rb') as file:\n",
    "#        pickled_model = pickle.load(file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b2296f64-9c89-4c8c-ad56-df75901162e5",
   "metadata": {},
   "outputs": [],
   "source": [
    "#pickled_model.predict(real_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1fa39aaf-0076-4a9a-a3e7-169a088f0381",
   "metadata": {},
   "outputs": [],
   "source": [
    "# predicted = pickled_model.predict(real_test)\n",
    "# probs = pickled_model.predicted_probabilities(real_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "717708f4-6fae-4c40-a8be-58d58ebec90b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# res = pd.DataFrame({'Run_date': datetime.datetime.now(),\n",
    "#                     'ISRC': real_data['ISRC'], \n",
    "#                     'Release_date':real_data['FIXED_RELEASE_DATE'],\n",
    "#                     'Model_spec': pickled_model.model,\n",
    "#                     'Predicted_probabilities_0': probs[:,0],\n",
    "#                     'Predicted_probabilities_1': probs[:,1],\n",
    "#                     'Prediction': predicted,\n",
    "#                     'Chart_date': real_data['MIN_CHART_DATE']})\n",
    "# res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b7fdce04-764c-41cf-8e17-5d3ec42b4392",
   "metadata": {},
   "outputs": [],
   "source": [
    "# def compute_flag(row):\n",
    "#     if row['Prediction'] == 0 and row['Chart_date'] == None:\n",
    "#         return 1\n",
    "#     elif row['Prediction'] == 1 and row['Chart_date'] != None:\n",
    "#         return 1\n",
    "#     else:\n",
    "#         return 0\n",
    "\n",
    "# res['Predicted_correctly'] = res.apply(compute_flag, axis=1)\n",
    "\n",
    "# res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fbbf8e90-558f-4a48-abc4-5d9043c1af2d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d39e401-b0aa-4038-a899-13bd37263d59",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "conda_python3",
   "language": "python",
   "name": "conda_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.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
