{"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":"","metadata":{"id":"5VxU_3Og3wH3"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Prediction of Student Performances from Game Play.**\n\n### The objective aims to predict the performance of students while playing an educational game. The data available to train a model is a large game log. We need to predict whether each student answered each question correctly, which involves binary classification for each question in each student session.\n---\n\n\n\n**Files:**\n\n***train.csv*** - the training set\n\n***test.csv*** - the test set\n\n***sample_submission.csv*** - a sample submission file in the correct format\n\n***train_labels.csv*** - correct value for all 18 questions for each session in the training set.\n\n\n\n---\n\n\n**Columns:**\n\n***session_id*** - the ID of the session the event took place in\n\n***index*** - the index of the event for the session\n\n***elapsed_time*** - how much time has passed (in milliseconds) between \nthe start of the session and when the event was recorded\n\n***event_name*** - the name of the event type\n\n***name*** - the event name (e.g. identifies whether a notebook_click is is opening or closing the notebook)\n\n***level*** - what level of the game the event occurred in (0 to 22)\n\n***page*** - the page number of the event (only for notebook-related events)\n\n***room_coor_x*** - the coordinates of the click in reference to the in-game room (only for click events)\n\n***room_coor_y*** - the coordinates of the click in reference to the in-game room (only for click events)\n\n***screen_coor_x*** - the coordinates of the click in reference to the player’s screen (only for click events)\n\n***screen_coor_y*** - the coordinates of the click in reference to the player’s screen (only for click events)\n\n***hover_duration*** - how long (in milliseconds) the hover happened for (only for hover events)\n\n***text*** - the text the player sees during this event\n\n***fqid*** - the fully qualified ID of the event\n\n***room_fqid*** - the fully qualified ID of the room the event took place in.\n\n***text_fqid*** - the fully qualified ID.\n\n***fullscreen*** - whether the player is in fullscreen mode\n\n***hq*** - whether the game is in high-quality\n\n***music***- whether the game music is on or off\n\n***level_group*** - which group of levels - and group of questions - this row belongs to (0-4, 5-12, 13-22)","metadata":{"id":"2P1cGa1HOZV9"}},{"cell_type":"code","source":"","metadata":{"id":"qTEuw5YWtcre"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Import the libraries :**","metadata":{"id":"-dDMo2zHnSsZ"}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as mpatches\nimport seaborn as sns","metadata":{"id":"utd2pMsLl8hS"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"PJ7ryngoteOr"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"2kGEx28BtsYj"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Load the data :**","metadata":{"id":"D4cdR-rhnJoh"}},{"cell_type":"code","source":"train_df = pd.read_csv('/content/Train set.csv')\ntest_df = pd.read_csv('/content/test.csv')\nlabels_df = pd.read_csv('/content/train_labels.csv')\nsubmission_df = pd.read_csv('/content/sample_submission.csv')","metadata":{"id":"AOSiadeCmEyh"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"4Ftm5_4rtrsv"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"hVErQaSVts0m"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Basic Investigation :**","metadata":{"id":"KXtCCGdAnDwS"}},{"cell_type":"code","source":"print(\"Train: rows\", len(train_df), \"| columns\", len(train_df.columns))\nprint(\"Test: rows\", len(test_df), \"| columns\", len(test_df.columns))\n\ntrain_df.head(2)","metadata":{"id":"c7TsZoZOmTbe","outputId":"43963731-6f2a-490b-f4ff-174a62175099"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"-2_yv1kMtt3Q"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"gHYZVVm5ttsp"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Missing Values :**","metadata":{"id":"4oElhvw9m1ro"}},{"cell_type":"code","source":"train_missing_ratios = train_df.isna().sum() / len(train_df)\ntest_missing_ratios = test_df.isna().sum() / len(test_df)\n\nplt.figure(figsize=(10, 4))\n\nplt.subplot(1, 2, 1)\nplt.bar(train_missing_ratios.index,\n        train_missing_ratios.values,\n        color=['blue' if ratio == 1 else 'magenta' for ratio in train_missing_ratios.values])\nplt.xlabel('Feature', fontsize=12)\nplt.ylabel('Missing values ratio', fontsize=12)\nplt.title('Missing values in TRAIN SET', fontsize=16)\nplt.xticks(rotation=90)\nplt.legend(handles=[mpatches.Patch(color='magenta'),\n                    mpatches.Patch(color='blue')], \n           labels=['Partially missing values', 'Completely missing values'])\n\nplt.subplot(1, 2, 2)\nplt.bar(test_missing_ratios.index,\n        test_missing_ratios.values,\n        color=['blue' if ratio == 1 else 'magenta' for ratio in test_missing_ratios.values])\nplt.title('Missing values in TEST SET', fontsize=16)\nplt.xticks(rotation=90)\n\nplt.tight_layout()\nplt.show()","metadata":{"id":"bUOBKHAvmsHT","outputId":"5c730eb7-7933-4f27-9aa2-2c87c12c263a"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Exploratory Data Analysis :**\n","metadata":{"id":"2St7LEOUqPrP"}},{"cell_type":"code","source":"print(\"The longest session  of the training set lasted about\",\n      int(train_df['elapsed_time'].max() / 8.64e7), \"days.\")\nprint(\"The longest session of the testing set lasted about\",\n      int(test_df['elapsed_time'].max() / 1000), \"sec.\")","metadata":{"id":"w2BepRggpnKt","outputId":"a6a8bf54-e22b-446c-e72c-999be2f28185"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"avg_elapsed_time = train_df.groupby('index')['elapsed_time'].mean() / 1000\n\nplt.figure(figsize=(10, 4))\nplt.plot(avg_elapsed_time)\nplt.axvline(2825, color='red', ls='--')\nplt.xlabel(\"Event index\", fontsize=12)\nplt.ylabel(\"Average elapsed time (sec)\", fontsize=12)\nplt.xlim([0, 4000])\nplt.legend(['Average elapsed time', 'Limit before non correlation'])\n\nplt.show()","metadata":{"id":"9x-0PyZ5pE2o","outputId":"4e796e78-e347-408a-f007-711328060c94"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"event_names = train_df['event_name'].value_counts()\nnames = train_df['name'].value_counts()\n\nprint(\"Number of event names:\", len(event_names))\nprint(\"Number of names:\", len(names))\n\nplt.figure(figsize=(10, 4))\n\nplt.subplot(1, 2, 1)\nplt.bar(event_names.index, event_names.values, color='orange')\nplt.ylabel(\"Occurence counts\", fontsize=12)\nplt.title(\"Frequency of the 'event names'\", fontsize=16)\nplt.xticks(rotation=70)\n\nplt.subplot(1, 2, 2)\nplt.bar(names.index, names.values, color='brown')\nplt.title(\"Frequency of the 'names'\", fontsize=16)\nplt.xticks(rotation=70)","metadata":{"id":"PqWHeR-bpxXk","outputId":"e60bcb6c-733e-40ab-959c-018c2cf2cf58"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"Qy0O7CWL4jKw"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.tight_layout()\nplt.show()\n\n# Pivot table\npivot_table = train_df.pivot_table(index='event_name', columns='name', aggfunc='size')\npivot_table = pivot_table.fillna(0).astype(int)\nplt.figure(figsize=(12, 4))\nsns.heatmap(pivot_table, annot=True, fmt='d', cmap='Greens')\nplt.title(\"Number of occurrences of 'event_name' and 'name'\", fontsize=16)\nplt.show()","metadata":{"id":"_cTFH_AN4Lye","outputId":"2d419ff1-ef0f-4968-866d-68157257febc"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"3hk_F1444jtz"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"grouped_df = train_df.groupby(['session_id', 'level'])\\\n    ['index'].count().reset_index()\ngrouped_df.columns = ['session_id', 'level', 'index_count']\nmean_counts = grouped_df.groupby('level').mean().drop('session_id', axis=1)\nmean_counts\n\nxrange = range(0, 23)\nplt.figure(figsize=(10, 4))\nplt.plot(mean_counts)\nplt.scatter(xrange, mean_counts, color='black')\nplt.title(\"Average number of events per question level\", fontsize=16)\nplt.xlabel(\"Average count of events\", fontsize=12)\nplt.ylabel(\"Level\", fontsize=12)\nplt.xticks(xrange)\nplt.show()","metadata":{"id":"7W6uANjbqYbT","outputId":"da275861-dffa-49db-d566-c544173bec74"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_page_number_counts = train_df['page'].value_counts().sort_index()\ntest_page_number_counts = test_df['page'].value_counts().sort_index()\nplt.figure(figsize=(10, 2))\n\nplt.subplot(1, 2, 1)\nplt.bar(range(0, 7), train_page_number_counts, color='blue')\nplt.xlabel(\"Page number\", fontsize=12)\nplt.ylabel(\"Count\", fontsize=12)\nplt.title(\"TRAIN SET\",\n          fontsize=16)\n\nplt.subplot(1, 2, 2)\nplt.bar(range(0, 7), test_page_number_counts, color='blue')\nplt.xlabel(\"Page number\", fontsize=12)\nplt.title(\"TEST SET\",\n          fontsize=16)\n\nplt.show()","metadata":{"id":"WGzZUe6wq1-9","outputId":"39ce9035-edc3-40ec-d8d1-af772f1b51a4"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_hover = train_df['hover_duration'].dropna() / 1000\ntest_hover = test_df['hover_duration'].dropna() / 1000\nxrange = range(0, 100, 10)\ntrain_percentiles , test_percentiles = [], []\nfor q in xrange:\n    train_perc = np.percentile(train_hover, q)\n    test_perc = np.percentile(test_hover, q)\n    train_percentiles.append(train_perc)\n    test_percentiles.append(test_perc)\n    \nplt.figure(figsize=(12, 4))\nplt.subplot(1, 2, 1)\nplt.plot(xrange, train_percentiles)\nplt.axhline(train_hover.median(), color='red', ls='--')\nplt.axhline(train_hover.mean(), color='orange', ls='--')\nplt.xticks(xrange)\nplt.yticks(range(0, 5))\nplt.legend(['Nb of events', 'Median', 'Mean'])\nplt.xlabel(\"Percentile\", fontsize=12)\nplt.ylabel(\"Hover duration in seconds\", fontsize=12)\nplt.title(\"TRAIN SET\", fontsize=16)\nplt.subplot(1, 2, 2)\nplt.plot(xrange, test_percentiles)\nplt.axhline(test_hover.median(), color='red', ls='--')\nplt.axhline(test_hover.mean(), color='orange', ls='--')\nplt.xticks(xrange)\nplt.xlabel(\"Percentile\", fontsize=12)\nplt.title(\"TEST SET\", fontsize=16)\nplt.show()","metadata":{"id":"9DkPNdwgq-gV","outputId":"a8f012aa-2976-4778-d245-2ae40caaf298"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_texts = train_df['text'].dropna().value_counts()\ntest_texts = test_df['text'].dropna().value_counts()\nprint(\"TRAIN | nb of unique texts:\", len(train_texts))\nprint('-' * 60)\nprint(train_texts, '\\n')\nprint(\"TEST | nb of unique texts:\", len(test_texts))\nprint('-' * 60)\nprint(test_texts, '\\n')","metadata":{"id":"lRVa6U3mrOEM","outputId":"c6771add-772b-4b9e-f112-52b83746c476"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_fqids = train_df['fqid'].value_counts()\ntrain_room_fqids = train_df['room_fqid'].value_counts()\ntrain_text_fqids = train_df['text_fqid'].value_counts()\ntest_fqids = test_df['fqid'].value_counts()\ntest_room_fqids = test_df['room_fqid'].value_counts()\ntest_text_fqids = test_df['text_fqid'].value_counts()\ntrain_fqid_bundle = [train_fqids, train_room_fqids, train_text_fqids]\ntest_fqid_bundle = [test_fqids, test_room_fqids, test_text_fqids]\nfqid_labels = [\"fqid\", \"room_fqid\", \"text_fqid\"]","metadata":{"id":"hhgN7NLlrSms"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def print_fqids(set_name, bundle):\n    for label, value in zip(fqid_labels, bundle):\n        print('-' * 60)\n        print(set_name, label)\n        print('-' * 60)\n        print(value)  \nprint_fqids('TRAIN', train_fqid_bundle)\nprint_fqids('TEST', test_fqid_bundle)\n","metadata":{"id":"s2kQVHXh3FZk","outputId":"fd447ff8-ee24-4beb-d356-b903a8f922fa"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = {\"Nb unique values\": fqid_labels,\n        \"TRAIN\": [len(x) for x in train_fqid_bundle],\n        \"TEST\": [len(x) for x in test_fqid_bundle]}\ndf = pd.DataFrame(data).set_index('Nb unique values')\ndf","metadata":{"id":"5KI9badN3FKC","outputId":"b2d047f8-1478-44e6-a74e-6fdb9a9c3599"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"1AM5FZFo5t08"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_df['question'] = labels_df['session_id'].apply(lambda x: int(x.split('_')[1][1:]))\ncorrect_ratios = []\nfor q in range(1, 19):\n    tmp = labels_df[labels_df['question'] == q]['correct']\n    ratio = tmp.sum() / len(tmp) \n    correct_ratios.append(ratio)\nxrange = range(1, 19)\nmean = np.mean(correct_ratios)","metadata":{"id":"s4btk_0yrVZo"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"IUSF1pHG56HK"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(8, 4))\nplt.bar(x=xrange, height=correct_ratios, color='purple')\nplt.axhline(mean, color='red', ls='--', lw=3)\nplt.xticks(xrange)\nplt.legend([f'Mean: {mean:.3f}'])\nplt.title(\"Correct answers per question\")\nplt.xlabel(\"Question number\")\nplt.ylabel(\"Ratio\")\nplt.show()","metadata":{"id":"0S6xVAm1uMpx","outputId":"70eed11e-203e-433c-8ac9-a976af675bdc"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"El9tQtE83EMK"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"1TJhFeYv6Wa6"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classes_count = labels_df['correct'].value_counts()\nprint(\"Classes count:\\n\", classes_count, \"\\n\")\nprint(\"Ratio:\\n\", classes_count / len(labels_df))\nlabels_df","metadata":{"id":"hfcOJSJVrbzQ","outputId":"99c80e97-a093-4366-e5bb-107861c5bfdd"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"FveZBx1Z5fRK"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"XVUgx76M5fLT"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"2k9VlyHiuN4J"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Interpretation :**\n\nThe following are the ***insights*** found -\n\n* It is quite a big dataframe (the train.csv file is more than 2GB large). It has more than **13** millions rows and a few features.\n* About **70%** of the answers are correct and 30% are incorrect.\n* The dataset is slightly **imbalanced**.\n* The train and test dataframes have **similar ratios** of missing values which are good news.\n* The labels only go up to level **18**, even though the questions extend up to level **22** in the training set.\n* In the training set, we can observe that the mean is significantly **higher than the median**, which is due to the presence of outliers where the user remained on hover for an extended period.\n","metadata":{"id":"FdIWkojurlqi"}}]}