{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport gc\n\nimport seaborn as sns\nimport matplotlib.pyplot as plt","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-04-18T14:35:09.609065Z","iopub.execute_input":"2023-04-18T14:35:09.609855Z","iopub.status.idle":"2023-04-18T14:35:10.842446Z","shell.execute_reply.started":"2023-04-18T14:35:09.609815Z","shell.execute_reply":"2023-04-18T14:35:10.841350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"thanks to chris for his amazing notebook on the screen coordinates where he has done heavy load of extracting game images.\ndiscussion [here](https://www.kaggle.com/competitions/predict-student-performance-from-game-play/discussion/387864) and notebook [here](https://www.kaggle.com/code/cdeotte/game-room-click-eda/comments)\n\nthis is the continuation of the discussion to find the relevance of the clicks data to answering the question.","metadata":{}},{"cell_type":"code","source":"def get_group_level(q):\n    qno = int(q[1:])\n    if qno < 4:\n        return '0-4'\n    elif qno < 14:\n        return '5-12'\n    return '13-22'\n\ndef get_wrong_answer_sessions(correct_df, lg):\n    if lg == '0-4':\n        th = 0\n    elif lg == '5-12':\n        th = 5\n    else:\n        th = 2\n    wrong_sessids = correct_df[(correct_df.level_group == lg) & \n                                    (correct_df.correct <= th)].session_id.unique()\n    return wrong_sessids\n\n\n\ndef get_correct_answer_sessions(correct_df, lg):\n    if lg == '0-4':\n        th = 1\n    elif lg == '5-12':\n        th = 7\n    else:\n        th = 4\n    wrong_sessids = correct_df[(correct_df.level_group == lg) & \n                                    (correct_df.correct >= th)].session_id.unique()\n    return wrong_sessids\n","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:35:10.844167Z","iopub.execute_input":"2023-04-18T14:35:10.844714Z","iopub.status.idle":"2023-04-18T14:35:10.852843Z","shell.execute_reply.started":"2023-04-18T14:35:10.844680Z","shell.execute_reply":"2023-04-18T14:35:10.851815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_label = pd.read_csv(\"/kaggle/input/predict-student-performance-from-game-play/train_labels.csv\")\ntrain_label['qno'] = train_label.session_id.apply(lambda session_id: session_id.split(\"_\")[-1])\ntrain_label['session_id'] = train_label.session_id.apply(lambda session_id: session_id.split(\"_\")[0]).astype(int)\ntrain_label['level_group'] = train_label.qno.apply(get_group_level)\n\ntrain_label.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:35:10.854410Z","iopub.execute_input":"2023-04-18T14:35:10.855043Z","iopub.status.idle":"2023-04-18T14:35:12.133461Z","shell.execute_reply.started":"2023-04-18T14:35:10.855006Z","shell.execute_reply":"2023-04-18T14:35:12.131723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"correct_df = train_label.groupby(['session_id', 'level_group'])[['correct']].sum().reset_index()\ncorrect_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:35:12.136469Z","iopub.execute_input":"2023-04-18T14:35:12.137549Z","iopub.status.idle":"2023-04-18T14:35:12.298667Z","shell.execute_reply.started":"2023-04-18T14:35:12.137495Z","shell.execute_reply":"2023-04-18T14:35:12.297780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ntrain_df = pd.read_csv(\"/kaggle/input/predict-student-performance-from-game-play/train.csv\",\n                       usecols=['session_id', \n                                'room_coor_x', 'room_coor_y',\n                                'screen_coor_x', 'screen_coor_y',\n                                'event_name', 'room_fqid',\n                                'level', 'level_group'],\n                       dtype={\n                           'level':np.int8, \n                           'room_coor_x': np.float16, 'room_coor_y': np.float16,\n                           'screen_coor_x': np.float16, 'screen_coor_y': np.float16,\n                           'event_name': 'category', \n                           'room_fqid': 'category'\n                       })\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:35:12.299920Z","iopub.execute_input":"2023-04-18T14:35:12.300409Z","iopub.status.idle":"2023-04-18T14:37:02.162633Z","shell.execute_reply.started":"2023-04-18T14:35:12.300376Z","shell.execute_reply":"2023-04-18T14:37:02.161331Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_click_event_stat(df, lg, event_name, ax):\n    df = df[(df.level_group == lg) & \n            (df.event_name == event_name)]\n    df = df.groupby('session_id')[['event_name']].count().reset_index()\n    \n    correct_sess = get_correct_answer_sessions(correct_df, lg)\n    wrong_sess = get_wrong_answer_sessions(correct_df, lg)\n    \n    df1 = df[df.session_id.isin(correct_sess)]\n    df2 = df[df.session_id.isin(wrong_sess)]\n\n    num_events1 = np.log(1+df1.event_name)\n    num_events2 = np.log(1+df2.event_name)\n    \n    mx1 = np.quantile(num_events1, 0.99)\n    mx2 = np.quantile(num_events2, 0.99)\n    \n    num_events1 = num_events1[num_events1<=mx1]\n    num_events2 = num_events2[num_events2<=mx2]\n    \n    print(\"==================level group:{} | event name:{}==================\".format(lg, event_name))\n    print(\"Mean\")\n    print(\"_______\")\n    print(\"Correct Events:{:.2f}\".format(num_events1.mean()))\n    print(\"Wrong Events:{:.2f}\".format(num_events2.mean()))\n    \n    print()\n    print()\n    print(\"STD\")\n    print(\"_____\")\n    print(\"Correct Events:{:.2f}\".format(num_events1.std()))\n    print(\"Wrong Events:{:.2f}\".format(num_events2.std()))\n    \n    sns.histplot(num_events1, bins=100, stat='density', label=\"correct\", ax=ax)\n    sns.histplot(num_events2, bins=100,stat='density',  label=\"wrong\", ax=ax)","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:02.164079Z","iopub.execute_input":"2023-04-18T14:37:02.164488Z","iopub.status.idle":"2023-04-18T14:37:02.174949Z","shell.execute_reply.started":"2023-04-18T14:37:02.164454Z","shell.execute_reply":"2023-04-18T14:37:02.174069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for lg in ['0-4', '5-12', '13-22']:\n    fig, ax=plt.subplots(1, 4, figsize=(12, 5))\n    fig.suptitle(\"level group:\"+ lg)\n    for i, event_name in enumerate(['navigate_click', 'person_click', 'object_click', 'cutscene_click']):\n        plot_click_event_stat(train_df, lg, event_name, ax[i])\n        ax[i].set_title(event_name)\n    plt.legend()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:02.176167Z","iopub.execute_input":"2023-04-18T14:37:02.176662Z","iopub.status.idle":"2023-04-18T14:37:32.000955Z","shell.execute_reply.started":"2023-04-18T14:37:02.176630Z","shell.execute_reply":"2023-04-18T14:37:31.999834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"def plot_click_scatters(event_name=None):\n    for lg in ['0-4', '5-12', '13-22']:\n        if lg == '0-4':\n            th = 2\n        elif lg == '5-12':\n            th = 7\n        else:\n            th = 3\n\n\n        wrong_sessids = correct_df[(correct_df.level_group == lg) & \n                                    (correct_df.correct < th)].session_id.unique()\n\n\n        levels = train_df[train_df.level_group == lg]['level'].unique()\n\n\n\n        print(\"level group:\", lg)\n        print(\"number of wrong answers:\", len(wrong_sessids))\n        for l in levels:\n            room_fqids = train_df[train_df.level ==l ]['room_fqid'].unique()\n            for room_fqid in room_fqids:\n                df = train_df[(train_df.level == l) & \n                              (train_df.room_fqid == room_fqid)]\n                \n                if event_name is not None:\n                    df = df[df.event_name == event_name]\n                if len(df) == 0:\n                    continue\n                    \n                df_correct = df[~df.session_id.isin(wrong_sessids)]\n                df_wrong = df[df.session_id.isin(wrong_sessids)]\n\n                fig, (ax0, ax1)=plt.subplots(1, 2, sharey=True)\n                fig.suptitle(\"level:{} | room fqid: {}\".format(l, room_fqid))\n\n                ax0.scatter(df_correct.room_coor_x, df_correct.room_coor_y, s=0.2)\n                ax1.scatter(df_wrong.room_coor_x, df_wrong.room_coor_y, s=0.2)\n\n                ax0.set_title(\"correct\")\n                ax1.set_title(\"wrong\")\n                plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:32.002237Z","iopub.execute_input":"2023-04-18T14:37:32.002629Z","iopub.status.idle":"2023-04-18T14:37:32.014496Z","shell.execute_reply.started":"2023-04-18T14:37:32.002597Z","shell.execute_reply":"2023-04-18T14:37:32.013066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:32.015919Z","iopub.execute_input":"2023-04-18T14:37:32.016369Z","iopub.status.idle":"2023-04-18T14:37:32.045026Z","shell.execute_reply.started":"2023-04-18T14:37:32.016332Z","shell.execute_reply":"2023-04-18T14:37:32.043761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(list(train_df.event_name.unique()))","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:32.048700Z","iopub.execute_input":"2023-04-18T14:37:32.049127Z","iopub.status.idle":"2023-04-18T14:37:32.186778Z","shell.execute_reply.started":"2023-04-18T14:37:32.049089Z","shell.execute_reply":"2023-04-18T14:37:32.185631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA on room clicks coordinates","metadata":{}},{"cell_type":"code","source":"correct_sess = get_correct_answer_sessions(correct_df, '0-4')\nwrong_sess = get_wrong_answer_sessions(correct_df, '0-4')","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:32.188300Z","iopub.execute_input":"2023-04-18T14:37:32.188638Z","iopub.status.idle":"2023-04-18T14:37:32.210921Z","shell.execute_reply.started":"2023-04-18T14:37:32.188605Z","shell.execute_reply":"2023-04-18T14:37:32.209588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_segment_id(v, vmin, seglen, N_SEG=20):\n    k = (v-vmin)//seglen\n    k = np.clip(k, 0, N_SEG)#.astype(int)\n    return k","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:32.212465Z","iopub.execute_input":"2023-04-18T14:37:32.213044Z","iopub.status.idle":"2023-04-18T14:37:32.218417Z","shell.execute_reply.started":"2023-04-18T14:37:32.213006Z","shell.execute_reply":"2023-04-18T14:37:32.217032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lg = '13-22'\nlvl = 16\nN_SEG = 10\nclick_map={}\n\ndef get_click_count_in_matrix(df_correct, df_wrong):\n    correct_mat = np.zeros((11,11))\n    wrong_mat = np.zeros((11,11))\n\n    for _,row in df_correct.iterrows():\n        xseg = int(row.xseg); yseg=int(row.yseg);\n        correct_mat[xseg][yseg] = row.nclick\n\n\n    for _,row in df_wrong.iterrows():\n        xseg = int(row.xseg); yseg=int(row.yseg);\n        wrong_mat[xseg][yseg] = row.nclick\n        \n    return (correct_mat, wrong_mat)\n\n#for event_name in ['cutscene_click', 'person_click', 'navigate_click', 'observation_click',\n                   #'notification_click', 'object_click', 'object_hover']:","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:32.507832Z","iopub.execute_input":"2023-04-18T14:37:32.508512Z","iopub.status.idle":"2023-04-18T14:37:32.516447Z","shell.execute_reply.started":"2023-04-18T14:37:32.508468Z","shell.execute_reply":"2023-04-18T14:37:32.515419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for lg in ['0-4', '5-12', '13-22']:\n    lvl_lst = train_df[train_df.level_group == lg]['level'].unique()\n    #for lvl in lvl_lst:\n    for room_fqid in train_df[(train_df.level_group == lg)].room_fqid.unique():\n        df = train_df[(train_df.level_group == lg) & \n                      #(train_df.level == lvl) & \n                      #(train_df.event_name == 'navigate_click') &\n                      (train_df.room_fqid == room_fqid)]\n\n        df = df[['session_id', 'room_coor_x', 'room_coor_y']]\n        df['nclick'] = 1\n\n        minX = df.room_coor_x.min(); maxX = df.room_coor_x.max()\n        minY = df.room_coor_y.min(); maxY = df.room_coor_y.max()\n\n        xlen = (maxX-minX)//N_SEG\n        ylen = (maxY-minY)//N_SEG\n\n\n        df['xseg'] = get_segment_id(df['room_coor_x'], minX, xlen)\n        df['yseg'] = get_segment_id(df['room_coor_y'], minY, ylen)\n\n        correct_sess = get_correct_answer_sessions(correct_df, lg)\n        wrong_sess = get_wrong_answer_sessions(correct_df, lg)\n\n        ncorrect = len(correct_sess)\n        nwrong = len(wrong_sess)\n\n        df_correct = df[df.session_id.isin(correct_sess)]\n        df_wrong = df[df.session_id.isin(wrong_sess)]\n\n\n        if len(df_correct)==0 or len(df_wrong)==0:\n            continue\n\n        df_correct = df_correct.groupby(['xseg', 'yseg'])[['nclick']].sum()/ncorrect\n        df_wrong = df_wrong.groupby(['xseg', 'yseg'])[['nclick']].sum()/nwrong\n\n        df_correct = df_correct.reset_index()\n        df_wrong = df_wrong.reset_index()\n\n        (correct_mat, wrong_mat) = get_click_count_in_matrix(df_correct, df_wrong)\n        mat_diff = correct_mat - wrong_mat\n\n        if click_map.get(lg, None) is None:\n            click_map[lg]={}\n        click_map[lg][room_fqid] = {'correct_mat':correct_mat,'wrong_mat':wrong_mat, 'mat_diff': mat_diff }","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:37:32.517963Z","iopub.execute_input":"2023-04-18T14:37:32.518638Z","iopub.status.idle":"2023-04-18T14:39:05.898009Z","shell.execute_reply.started":"2023-04-18T14:37:32.518599Z","shell.execute_reply":"2023-04-18T14:39:05.896977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mat_diff_df=[]\nfor lg in ['0-4', '5-12', '13-22']:\n    for room_fqid in click_map[lg].keys():\n        mat_diff = click_map[lg][room_fqid]['mat_diff']\n        mat_diff_df.append({\n            'level_group':lg,\n            'room_fqid': room_fqid,\n            'click_mean': np.mean(mat_diff),\n            'click_std': np.std(mat_diff)})\nmat_diff_df = pd.DataFrame.from_dict(mat_diff_df)\nmat_diff_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:39:05.899456Z","iopub.execute_input":"2023-04-18T14:39:05.899996Z","iopub.status.idle":"2023-04-18T14:39:05.918082Z","shell.execute_reply.started":"2023-04-18T14:39:05.899962Z","shell.execute_reply":"2023-04-18T14:39:05.916875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mat_diff_df.sort_values(\"click_mean\", ascending=False)","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:39:05.919691Z","iopub.execute_input":"2023-04-18T14:39:05.920063Z","iopub.status.idle":"2023-04-18T14:39:05.939587Z","shell.execute_reply.started":"2023-04-18T14:39:05.920030Z","shell.execute_reply":"2023-04-18T14:39:05.938664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for lg in click_map.keys():\n    for room_fqid in click_map[lg].keys():\n        mat_diff = click_map[lg][room_fqid]['mat_diff']\n        fig, ax=plt.subplots(1, 2, figsize=(12, 5))\n        fig.suptitle(lg+\" : \"+str(lvl)+\" : \"+room_fqid)\n\n        sns.heatmap(mat_diff, ax=ax[0])\n        sns.histplot(x=mat_diff.flatten(), ax=ax[1])\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-18T14:52:13.930046Z","iopub.execute_input":"2023-04-18T14:52:13.930540Z","iopub.status.idle":"2023-04-18T14:52:34.257716Z","shell.execute_reply.started":"2023-04-18T14:52:13.930485Z","shell.execute_reply":"2023-04-18T14:52:34.254647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}