{"cells":[{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"a4f8b8c9-41c0-5bc0-c437-a2f6a56873e8"},"outputs":[],"source":"import numpy as np\nimport pandas as pd\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.neighbors import KNeighborsClassifier\n\ndef 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 \ndef 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   \ndef 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    \nif __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":"1b7f0a09-ca18-be50-04b9-6f8a6359682f"},"outputs":[],"source":"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)"}],"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}