{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "e5ef039d-bedd-e676-eb9c-a1d461d30637"
      },
      "source": [
        "test"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "b2bea244-509e-177d-b33e-1acaca42f30f"
      },
      "outputs": [],
      "source": [
        ""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "e8e5c6fc-539a-a639-5fb1-1d013a3b6308"
      },
      "outputs": [],
      "source": [
        "# coding: utf-8\n",
        "__author__ = 'Sandro Vega Pons : https://www.kaggle.com/svpons'\n",
        "\n",
        "'''Partially based on grid_plus_classifier script:\n",
        "https://www.kaggle.com/svpons/facebook-v-predicting-check-ins/grid-plus-classifier\n",
        "'''\n",
        "\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "from sklearn.preprocessing import LabelEncoder\n",
        "from sklearn.neighbors import KNeighborsClassifier\n",
        "\n",
        "\n",
        "def prepare_data(df, n_cell_x, n_cell_y):\n",
        "    \"\"\"\n",
        "    Feature engineering and computation of the grid.\n",
        "    \"\"\"\n",
        "    #Creating the grid\n",
        "    size_x = 10. / n_cell_x\n",
        "    size_y = 10. / n_cell_y\n",
        "    eps = 0.00001  \n",
        "    xs = np.where(df.x.values < eps, 0, df.x.values - eps)\n",
        "    ys = np.where(df.y.values < eps, 0, df.y.values - eps)\n",
        "    pos_x = (xs / size_x).astype(np.int)\n",
        "    pos_y = (ys / size_y).astype(np.int)\n",
        "    df['grid_cell'] = pos_y * n_cell_x + pos_x\n",
        "    \n",
        "    #Feature engineering\n",
        "    fw = [500, 1000, 4, 3, 1./22., 2, 10] #feature weights (black magic here)\n",
        "    df.x = df.x.values * fw[0]\n",
        "    df.y = df.y.values * fw[1]\n",
        "    initial_date = np.datetime64('2014-01-01T01:01', dtype='datetime64[m]') \n",
        "    d_times = pd.DatetimeIndex(initial_date + np.timedelta64(int(mn), 'm') \n",
        "                               for mn in df.time.values)    \n",
        "    df['hour'] = d_times.hour * fw[2]\n",
        "    df['weekday'] = d_times.weekday * fw[3]\n",
        "    df['day'] = (d_times.dayofyear * fw[4]).astype(int)\n",
        "    df['month'] = d_times.month * fw[5]\n",
        "    df['year'] = (d_times.year - 2013) * fw[6]\n",
        "\n",
        "    df = df.drop(['time'], axis=1) \n",
        "    return df\n",
        "    \n",
        "\n",
        "def process_one_cell(df_train, df_test, grid_id, th):\n",
        "    \"\"\"   \n",
        "    Classification inside one grid cell.\n",
        "    \"\"\"   \n",
        "    #Working on df_train\n",
        "    df_cell_train = df_train.loc[df_train.grid_cell == grid_id]\n",
        "    place_counts = df_cell_train.place_id.value_counts()\n",
        "    mask = (place_counts[df_cell_train.place_id.values] >= th).values\n",
        "    df_cell_train = df_cell_train.loc[mask]\n",
        "\n",
        "    #Working on df_test\n",
        "    df_cell_test = df_test.loc[df_test.grid_cell == grid_id]\n",
        "    row_ids = df_cell_test.index\n",
        "    \n",
        "    #Preparing data\n",
        "    le = LabelEncoder()\n",
        "    y = le.fit_transform(df_cell_train.place_id.values)\n",
        "    X = df_cell_train.drop(['place_id', 'grid_cell'], axis=1).values.astype(int)\n",
        "    X_test = df_cell_test.drop(['grid_cell'], axis = 1).values.astype(int)\n",
        "    \n",
        "    #Applying the classifier\n",
        "    clf = KNeighborsClassifier(n_neighbors=25, weights='distance', \n",
        "                               metric='manhattan')\n",
        "    clf.fit(X, y)\n",
        "    y_pred = clf.predict_proba(X_test)\n",
        "    pred_labels = le.inverse_transform(np.argsort(y_pred, axis=1)[:,::-1][:,:3])    \n",
        "    return pred_labels, row_ids\n",
        "   \n",
        "   \n",
        "def process_grid(df_train, df_test, th, n_cells):\n",
        "    \"\"\"\n",
        "    Iterates over all grid cells, aggregates the results and makes the\n",
        "    submission.\n",
        "    \"\"\" \n",
        "    preds = np.zeros((df_test.shape[0], 3), dtype=int)\n",
        "    \n",
        "    for g_id in range(n_cells):\n",
        "        if g_id % 100 == 0:\n",
        "            print('iter: %s' %(g_id))\n",
        "        \n",
        "        #Applying classifier to one grid cell\n",
        "        pred_labels, row_ids = process_one_cell(df_train, df_test, g_id, th)\n",
        "\n",
        "        #Updating predictions\n",
        "        preds[row_ids] = pred_labels\n",
        "\n",
        "    print('Generating submission file ...')\n",
        "    #Auxiliary dataframe with the 3 best predictions for each sample\n",
        "    df_aux = pd.DataFrame(preds, dtype=str, columns=['l1', 'l2', 'l3'])  \n",
        "    \n",
        "    #Concatenating the 3 predictions for each sample\n",
        "    ds_sub = df_aux.l1.str.cat([df_aux.l2, df_aux.l3], sep=' ')\n",
        "    \n",
        "    #Writting to csv\n",
        "    ds_sub.name = 'place_id'\n",
        "    ds_sub.to_csv('sub_knn.csv', index=True, header=True, index_label='row_id')  \n",
        "      \n",
        "\n",
        "if __name__ == '__main__':\n",
        "    \"\"\"\n",
        "    \"\"\"\n",
        "    print('Loading data ...')\n",
        "    df_train = pd.read_csv('../input/train.csv',\n",
        "                           usecols=['row_id','x','y','time','place_id'], \n",
        "                           index_col = 0)\n",
        "    df_test = pd.read_csv('../input/test.csv',\n",
        "                          usecols=['row_id','x','y','time'],\n",
        "                          index_col = 0)\n",
        " \n",
        "    #Defining the size of the grid\n",
        "    n_cell_x = 20\n",
        "    n_cell_y = 40 \n",
        "    \n",
        "    print('Preparing train data')\n",
        "    df_train = prepare_data(df_train, n_cell_x, n_cell_y)\n",
        "    \n",
        "    print('Preparing test data')\n",
        "    df_test = prepare_data(df_test, n_cell_x, n_cell_y)\n",
        "    \n",
        "    #Solving classification problems inside each grid cell\n",
        "    th = 5 #Keeping place_ids with more than th samples.   \n",
        "    process_grid(df_train, df_test, th, n_cell_x*n_cell_y)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "fe259944-cfb1-7b2a-a344-3b52d8c0a182"
      },
      "outputs": [],
      "source": [
        ""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "9d7e27c5-7ef6-03d8-e6fc-8d2d4c78904a"
      },
      "outputs": [],
      "source": [
        ""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "5592d9cf-daac-e846-82d2-bab69be0eca2"
      },
      "outputs": [],
      "source": [
        ""
      ]
    }
  ],
  "metadata": {
    "_change_revision": 0,
    "_is_fork": false,
    "kernelspec": {
      "display_name": "Python 3",
      "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.5.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}