{"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":"markdown","source":"\n# EDA and insights - Bundesliga Data Shootout\n\nThe following notebook consists of a simple EDA of the dataset.\n\n* All the graphs are visualised using seaborn\n* The conclusions from the EDA is presented in the last cell\n\nPlease **upvote** and feel free to suggest changes and provide feedback. Thank you :)","metadata":{}},{"cell_type":"code","source":"import seaborn as sns\nimport pandas as pd\nimport numpy as np","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:12:11.568716Z","iopub.execute_input":"2022-07-31T02:12:11.569013Z","iopub.status.idle":"2022-07-31T02:12:11.574438Z","shell.execute_reply.started":"2022-07-31T02:12:11.568990Z","shell.execute_reply":"2022-07-31T02:12:11.573065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Get data","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv(\"../input/dfl-bundesliga-data-shootout/train.csv\")","metadata":{"execution":{"iopub.status.busy":"2022-07-31T01:06:10.803506Z","iopub.execute_input":"2022-07-31T01:06:10.803808Z","iopub.status.idle":"2022-07-31T01:06:10.841239Z","shell.execute_reply.started":"2022-07-31T01:06:10.803786Z","shell.execute_reply":"2022-07-31T01:06:10.840484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-31T01:06:14.632167Z","iopub.execute_input":"2022-07-31T01:06:14.632515Z","iopub.status.idle":"2022-07-31T01:06:14.650610Z","shell.execute_reply.started":"2022-07-31T01:06:14.632488Z","shell.execute_reply":"2022-07-31T01:06:14.649649Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.describe(include=\"object\")","metadata":{"execution":{"iopub.status.busy":"2022-07-31T01:20:45.847835Z","iopub.execute_input":"2022-07-31T01:20:45.848897Z","iopub.status.idle":"2022-07-31T01:20:45.868508Z","shell.execute_reply.started":"2022-07-31T01:20:45.848863Z","shell.execute_reply":"2022-07-31T01:20:45.867408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualizing the data distributions","metadata":{}},{"cell_type":"code","source":"# Visualizing the distribution of the three classes\ng = sns.catplot(\n    data = df[(df['event']!=\"start\") & (df['event']!='end')],\n    x = \"event\",\n    kind = \"count\"\n)","metadata":{"execution":{"iopub.status.busy":"2022-07-31T01:48:35.673927Z","iopub.execute_input":"2022-07-31T01:48:35.674242Z","iopub.status.idle":"2022-07-31T01:48:35.854569Z","shell.execute_reply.started":"2022-07-31T01:48:35.674218Z","shell.execute_reply":"2022-07-31T01:48:35.853866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualizing the distribution of the event attributes overall\ng = sns.catplot(\n    data = df[(df['event']!=\"start\") & (df['event']!='end')],\n    y = \"event_attributes\",\n    kind = \"count\",\n    height=5,\n    aspect=3,\n    orientation='horizontal'\n)","metadata":{"execution":{"iopub.status.busy":"2022-07-31T01:57:48.892302Z","iopub.execute_input":"2022-07-31T01:57:48.892652Z","iopub.status.idle":"2022-07-31T01:57:49.153964Z","shell.execute_reply.started":"2022-07-31T01:57:48.892624Z","shell.execute_reply":"2022-07-31T01:57:49.152487Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualizing the distribution of the event attributes for each event\ng = sns.catplot(\n    data = df[(df['event']!=\"start\") & (df['event']!='end')],\n    y = \"event_attributes\",\n    col = \"event\",\n    kind = \"count\",\n    height=6,\n    aspect=1.5,\n    orientation='horizontal'\n)","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:01:49.874997Z","iopub.execute_input":"2022-07-31T02:01:49.875383Z","iopub.status.idle":"2022-07-31T02:01:50.453656Z","shell.execute_reply.started":"2022-07-31T02:01:49.875356Z","shell.execute_reply":"2022-07-31T02:01:50.452742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Understanding the *start* and *end* intervals\n* This gives us idea about how many extra frames we get every class","metadata":{}},{"cell_type":"code","source":"df_start = df[df['event'] == 'start'].reset_index()\ndf_end = df[df['event'] == 'end'].reset_index()\n\nintervals = pd.DataFrame()\nintervals['frames'] = df_end['time'] -  df_start['time']","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:17:16.733812Z","iopub.execute_input":"2022-07-31T02:17:16.734960Z","iopub.status.idle":"2022-07-31T02:17:16.750030Z","shell.execute_reply.started":"2022-07-31T02:17:16.734897Z","shell.execute_reply":"2022-07-31T02:17:16.748651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Distribution of intervals\ng = sns.catplot(data=intervals, x='frames',  kind = \"box\", height = 5, aspect = 4)","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:18:08.641571Z","iopub.execute_input":"2022-07-31T02:18:08.641953Z","iopub.status.idle":"2022-07-31T02:18:08.808905Z","shell.execute_reply.started":"2022-07-31T02:18:08.641923Z","shell.execute_reply":"2022-07-31T02:18:08.807822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Mean numbers of frames between 'start' and 'end' is:\", intervals.mean())\nprint(\"Standard deviation of num of frames between 'start' and 'end' is:\", intervals.std())\nprint(\"Median numbers of frames between 'start' and 'end' is:\", intervals.median())","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:18:29.709543Z","iopub.execute_input":"2022-07-31T02:18:29.709843Z","iopub.status.idle":"2022-07-31T02:18:29.722070Z","shell.execute_reply.started":"2022-07-31T02:18:29.709819Z","shell.execute_reply":"2022-07-31T02:18:29.720583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Time intervals and events\n\n* Attempt to find out if there is a relationship between the events and time in the match when they occur\n* Let's use only the full length matches","metadata":{}},{"cell_type":"code","source":"df['video_id'].unique()","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:58:53.678287Z","iopub.execute_input":"2022-07-31T02:58:53.678593Z","iopub.status.idle":"2022-07-31T02:58:53.685927Z","shell.execute_reply.started":"2022-07-31T02:58:53.678570Z","shell.execute_reply":"2022-07-31T02:58:53.684635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_length_videos = [\"1606b0e6_0\", \"1606b0e6_1\", \"35bd9041_0\", \"35bd9041_1\", \"3c993bd2_0\", \"3c993bd2_1\", \"cfbe2e94_0\", \"cfbe2e94_1\"]\nfull_length_videos  = str(\"|\".join(full_length_videos))","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:58:54.638639Z","iopub.execute_input":"2022-07-31T02:58:54.638981Z","iopub.status.idle":"2022-07-31T02:58:54.644570Z","shell.execute_reply.started":"2022-07-31T02:58:54.638955Z","shell.execute_reply":"2022-07-31T02:58:54.643290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_length_df = df[df['video_id'].str.contains(full_length_videos)]","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:58:55.270072Z","iopub.execute_input":"2022-07-31T02:58:55.270555Z","iopub.status.idle":"2022-07-31T02:58:55.281279Z","shell.execute_reply.started":"2022-07-31T02:58:55.270530Z","shell.execute_reply":"2022-07-31T02:58:55.280355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's divide the half length videos into 2 segments\n# Therefore total of 4 segments in each full length match\nfull_length_df['timegroup'] = pd.qcut(full_length_df['time'], 2)","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:59:05.122373Z","iopub.execute_input":"2022-07-31T02:59:05.122680Z","iopub.status.idle":"2022-07-31T02:59:05.133165Z","shell.execute_reply.started":"2022-07-31T02:59:05.122657Z","shell.execute_reply":"2022-07-31T02:59:05.132049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_length_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:59:05.381529Z","iopub.execute_input":"2022-07-31T02:59:05.383455Z","iopub.status.idle":"2022-07-31T02:59:05.396852Z","shell.execute_reply.started":"2022-07-31T02:59:05.383394Z","shell.execute_reply":"2022-07-31T02:59:05.395564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### When does challenge event usually occur in the match","metadata":{}},{"cell_type":"code","source":"g = sns.catplot(\n    data = full_length_df[full_length_df['event']=='challenge'],\n    y = 'timegroup',\n    kind = 'count',\n    orientation=\"horizontal\",\n    height=6,\n    aspect = 2,\n    col = 'video_id',\n    col_wrap=2,\n\n)","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:59:55.097347Z","iopub.execute_input":"2022-07-31T02:59:55.097653Z","iopub.status.idle":"2022-07-31T02:59:56.171990Z","shell.execute_reply.started":"2022-07-31T02:59:55.097630Z","shell.execute_reply":"2022-07-31T02:59:56.170675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### When does play event usually occur in the match","metadata":{}},{"cell_type":"code","source":"g = sns.catplot(\n    data = full_length_df[full_length_df['event']=='play'],\n    y = 'timegroup',\n    kind = 'count',\n    orientation=\"horizontal\",\n    height=6,\n    aspect = 2,\n    col = 'video_id',\n    col_wrap=2,\n\n)","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:59:56.173784Z","iopub.execute_input":"2022-07-31T02:59:56.174085Z","iopub.status.idle":"2022-07-31T02:59:57.211448Z","shell.execute_reply.started":"2022-07-31T02:59:56.174057Z","shell.execute_reply":"2022-07-31T02:59:57.210440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### When does throwin event usually occur in the match","metadata":{}},{"cell_type":"code","source":"g = sns.catplot(\n    data = full_length_df[full_length_df['event']=='throwin'],\n    y = 'timegroup',\n    kind = 'count',\n    orientation=\"horizontal\",\n    height=6,\n    aspect = 2,\n    col = 'video_id',\n    col_wrap=2,\n\n)","metadata":{"execution":{"iopub.status.busy":"2022-07-31T02:59:57.212544Z","iopub.execute_input":"2022-07-31T02:59:57.212764Z","iopub.status.idle":"2022-07-31T02:59:58.537829Z","shell.execute_reply.started":"2022-07-31T02:59:57.212741Z","shell.execute_reply":"2022-07-31T02:59:58.536901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Conclusion and Insights\n\n* The dataset is imbalanced with `play` having relatively more data samples than the others (Can combat with class weights, data augmentation, sampling strategies)\n* The `event_attributes` are also imbalanced, looking at it's distribution within the events, and even though it seems like a diffrentating factor, we won't have `event_attributes` during inference, it won't be cruicial for training\n* Looking at the intervals between `start` and `end`, there seems to be an average of 3 seconds (3 frames, if we take one frame per second) for any event, with some outliers(Maximum 14 seconds). This is good because the image samples for each event will be 3x more approx\n* The time does not seem to highly correlate with when a particular event might happen. It was expected, but good to logically rule out :)","metadata":{}}]}