{"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":"# AI4Code EDA","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:33:45.266325Z","iopub.execute_input":"2022-06-22T15:33:45.267001Z","iopub.status.idle":"2022-06-22T15:33:46.492741Z","shell.execute_reply.started":"2022-06-22T15:33:45.266848Z","shell.execute_reply":"2022-06-22T15:33:46.4918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df=pd.read_parquet('../input/ai4code-train/train_with_features.parquet')\nprint('train_df successful')\nlanguage_mapping=pd.read_parquet('../input/ai4code-train/language_mapping.parquet')\nprint('language_mapping successful')\norder_df=pd.read_csv('../input/AI4Code/train_orders.csv')\nprint('order_df successful')\nnb_with_duplicate_cells_df=pd.read_parquet('../input/ai4code-train/nb_with_duplicate_cells.parquet')\nprint('nb_with_duplicate_cells_df successful')","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:33:46.494659Z","iopub.execute_input":"2022-06-22T15:33:46.495076Z","iopub.status.idle":"2022-06-22T15:35:19.784217Z","shell.execute_reply.started":"2022-06-22T15:33:46.495041Z","shell.execute_reply":"2022-06-22T15:35:19.783013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load the data and take a pick into the columns","metadata":{}},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:19.785778Z","iopub.execute_input":"2022-06-22T15:35:19.786273Z","iopub.status.idle":"2022-06-22T15:35:19.814302Z","shell.execute_reply.started":"2022-06-22T15:35:19.786224Z","shell.execute_reply":"2022-06-22T15:35:19.813251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(language_mapping))\nlanguage_mapping.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:19.816661Z","iopub.execute_input":"2022-06-22T15:35:19.817048Z","iopub.status.idle":"2022-06-22T15:35:19.829235Z","shell.execute_reply.started":"2022-06-22T15:35:19.817015Z","shell.execute_reply":"2022-06-22T15:35:19.82793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"order_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:19.830577Z","iopub.execute_input":"2022-06-22T15:35:19.830951Z","iopub.status.idle":"2022-06-22T15:35:19.845116Z","shell.execute_reply.started":"2022-06-22T15:35:19.830908Z","shell.execute_reply":"2022-06-22T15:35:19.843981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"order_dict={row['id']:row['cell_order'].split() for index, row in order_df.iterrows()}","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:19.846663Z","iopub.execute_input":"2022-06-22T15:35:19.847616Z","iopub.status.idle":"2022-06-22T15:35:29.183315Z","shell.execute_reply.started":"2022-06-22T15:35:19.847582Z","shell.execute_reply":"2022-06-22T15:35:29.182354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(nb_with_duplicate_cells_df))\nnb_with_duplicate_cells_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:29.18481Z","iopub.execute_input":"2022-06-22T15:35:29.185316Z","iopub.status.idle":"2022-06-22T15:35:29.195573Z","shell.execute_reply.started":"2022-06-22T15:35:29.18527Z","shell.execute_reply":"2022-06-22T15:35:29.194649Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Analysis","metadata":{}},{"cell_type":"code","source":"markdown_mean=np.mean(train_df['cell_type']=='markdown')\nprint(f'mean number of markdown cells: {markdown_mean*100}%')\n\nsns.countplot(x='cell_type',data=train_df)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:29.196967Z","iopub.execute_input":"2022-06-22T15:35:29.198084Z","iopub.status.idle":"2022-06-22T15:35:37.949037Z","shell.execute_reply.started":"2022-06-22T15:35:29.198041Z","shell.execute_reply":"2022-06-22T15:35:37.948065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'mean number of notebooks with duplicates: {nb_with_duplicate_cells_df[\"has_duplicates\"].mean()*100}%')\n\nsns.countplot(x='has_duplicates',data=nb_with_duplicate_cells_df)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:37.950667Z","iopub.execute_input":"2022-06-22T15:35:37.951293Z","iopub.status.idle":"2022-06-22T15:35:38.158629Z","shell.execute_reply.started":"2022-06-22T15:35:37.951246Z","shell.execute_reply":"2022-06-22T15:35:38.157463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I expected the mean number of markdown cells to be higher for the notebooks with duplicates than the whole dataset. However, it was higher for the whole dataset. After checking the duplicated cells (at the end of the notebook). I think most notebooks that have duplicated cells were lazy and did not want to write a lot of markdown cells.","metadata":{}},{"cell_type":"code","source":"english_mean=np.mean(language_mapping['language']=='en')\n# print(f'mean number of english nbs: {english_mean*100}%')\n\ndata=[english_mean,1-english_mean]\nkeys=['english','other']\nstartangle=90\nshadow=True\nexplode=[0.1,0]\nradius=1.9\n\n# define Seaborn color palette to use\npalette_color = sns.color_palette('bright')\n  \n# plotting data on chart\nplt.pie(data, labels=keys, colors=palette_color,radius=radius, autopct='%.1f%%',shadow=shadow,explode=explode,startangle=startangle)\n\nplt.title('Proportion of english notebooks knowing the notebook have duplicates',pad=80)\n# displaying chart\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:38.161237Z","iopub.execute_input":"2022-06-22T15:35:38.16167Z","iopub.status.idle":"2022-06-22T15:35:38.345381Z","shell.execute_reply.started":"2022-06-22T15:35:38.161634Z","shell.execute_reply":"2022-06-22T15:35:38.34396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(25,5))\nsns.countplot(x='language',data=language_mapping)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:38.348755Z","iopub.execute_input":"2022-06-22T15:35:38.349344Z","iopub.status.idle":"2022-06-22T15:35:39.070908Z","shell.execute_reply.started":"2022-06-22T15:35:38.349294Z","shell.execute_reply":"2022-06-22T15:35:39.069926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<p>\n    Dealing with notebooks containing duplicate cells is tricky. Misordering a notebook affects the order of all other cells. Moreover, depending on how the selected model works, the model can get confused on predictions since 2 exact inputs have different positions. Do these cells come right after each other in the notebooks? what about removing one and putting it either always before/after the duplicate?\n</p>","metadata":{}},{"cell_type":"code","source":"tmp_df=nb_with_duplicate_cells_df.join(language_mapping)\ntmp_df=tmp_df[tmp_df['has_duplicates']==1]\n\nassert len(tmp_df)==np.sum(tmp_df['has_duplicates']==1), 'There is something wrong'\n\nenglish_mean=np.mean(tmp_df['language']=='en')\n\ndata=[english_mean,1-english_mean]\nkeys=['english','other']\nstartangle=90\nshadow=True\nexplode=[0.1,0]\nradius=1.9\n\n# define Seaborn color palette to use\npalette_color = sns.color_palette('bright')\n  \n# plotting data on chart\nplt.pie(data, labels=keys, colors=palette_color,radius=radius, autopct='%.1f%%',shadow=shadow,explode=explode,startangle=startangle)\n\nplt.title('Proportion of english notebooks knowing the notebook have duplicates',pad=80)\n\n# displaying chart\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:39.072522Z","iopub.execute_input":"2022-06-22T15:35:39.073007Z","iopub.status.idle":"2022-06-22T15:35:39.282595Z","shell.execute_reply.started":"2022-06-22T15:35:39.072962Z","shell.execute_reply":"2022-06-22T15:35:39.281286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<p>\n    The proprotion of english markdown cells is equal in both, the whole dataset and the dataset having duplicate code cells.\n</p>\n\n<p>\n    Next I need to check the if duplicate cells are alongside each other or distributed through out the notebook.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(25,5))\nsns.countplot(x='language',data=tmp_df)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:39.284394Z","iopub.execute_input":"2022-06-22T15:35:39.285023Z","iopub.status.idle":"2022-06-22T15:35:40.124509Z","shell.execute_reply.started":"2022-06-22T15:35:39.284971Z","shell.execute_reply":"2022-06-22T15:35:40.123437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Get the markdown cells of notebooks with duplicate cells\nmarkdown_df=train_df[(train_df['cell_type']=='markdown')].copy()\nmarkdown_df=markdown_df[markdown_df['has_duplicates']==True]\nprint('length of markdown cells',len(markdown_df))\n\nid_to_dup_order={}\n\ni=0\nfor index, group_df in markdown_df.reset_index().groupby(['id']):\n    \n#     print(index)\n#     print(group_df)\n#     print('\\n\\n',group_df['source'].nunique())\n#     print(len(group_df))\n    duplicated_cells=group_df[group_df['source'].duplicated(keep=False)]\n    if i<10: \n        print(duplicated_cells[['cell_id','source']])\n        print('-----------------------')\n    \n    dup_order=[]\n    for cell_id in duplicated_cells['cell_id']:\n        dup_order.append(order_dict[index].index(cell_id))\n    \n    #check if notebook has more than 1 cell that has a duplicate.\n    id_to_dup_order[index]=(duplicated_cells['source'].nunique()==1,dup_order)\n    i+=1\n    \ndel markdown_df","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:40.125719Z","iopub.execute_input":"2022-06-22T15:35:40.126463Z","iopub.status.idle":"2022-06-22T15:35:47.994365Z","shell.execute_reply.started":"2022-06-22T15:35:40.126423Z","shell.execute_reply":"2022-06-22T15:35:47.993518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"iterations=10\n\ni=0\nfor key, value in id_to_dup_order.items():\n    print(f'{key}: {value}')\n    \n    if i > iterations: break\n    i+=1","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:47.995815Z","iopub.execute_input":"2022-06-22T15:35:47.996277Z","iopub.status.idle":"2022-06-22T15:35:48.003213Z","shell.execute_reply.started":"2022-06-22T15:35:47.996235Z","shell.execute_reply":"2022-06-22T15:35:48.001742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<p> \n    It looks like the duplicates are lazy comments or some generic line that they add to many to experiments. For example, there is a markdown text that just says export, and there are 3 of them! Maybe when exporting many files, the owner of the document just writes export. Another example is the one that starts with \"Green markers denote crimes commited within\". It is similar to adding footnotes to graphs in reports. You add the same text to all graphs to make it clear.\n</p>\n\n<p>\n    How to deal with this values? If we switch any of these cells, the meaning does not change and it is not wrong. Thus, could potentially become malicious examples that may confuse the model. An idea is to consider the 3 of them the same cell (same 'cell_id').\n</p>","metadata":{}},{"cell_type":"code","source":"def get_token_statistics(df,column='cell_type',value='markdown',spliter=' ',lower_percentile=10,upper_percentile=95,title=''):\n    df_copy=df.copy()\n    \n    df_copy=df_copy[df_copy[column]==value]\n    \n    #Get the number of tokens\n    df_copy['cell_len']=df_copy['source'].apply(lambda source: len(str(source).split(spliter)))\n    \n    print(f'The max number of tokens: {np.max(df_copy[\"cell_len\"])}')\n    print(f'The min number of tokens: {np.min(df_copy[\"cell_len\"])}')\n    print(f'The mean number of tokens: {np.mean(df_copy[\"cell_len\"])}')\n    print(f'The median number of tokens: {np.median(df_copy[\"cell_len\"])}')\n    print(f'The std number of tokens: {np.std(df_copy[\"cell_len\"])}')\n    print(f'The {upper_percentile} percentile of the number of tokens: {np.percentile(df_copy[\"cell_len\"],upper_percentile)}')\n    print(f'The {lower_percentile} percentile of the number of tokens: {np.percentile(df_copy[\"cell_len\"],lower_percentile)}')\n    \n    sns.displot(data=df_copy.iloc[:50000].reset_index(),x='cell_len',kind='kde',hue='cell_type')\n    \n    ax=plt.gca()\n    ax.set_title(title)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:48.004796Z","iopub.execute_input":"2022-06-22T15:35:48.00528Z","iopub.status.idle":"2022-06-22T15:35:48.01857Z","shell.execute_reply.started":"2022-06-22T15:35:48.005237Z","shell.execute_reply":"2022-06-22T15:35:48.017514Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"title='Number words in markdown cells'\nget_token_statistics(train_df,title=title)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:48.020119Z","iopub.execute_input":"2022-06-22T15:35:48.020832Z","iopub.status.idle":"2022-06-22T15:35:57.647148Z","shell.execute_reply.started":"2022-06-22T15:35:48.020797Z","shell.execute_reply":"2022-06-22T15:35:57.645954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<p>\n    The 95<sup>th</sup> percentile is 115. Thus, maybe a 128 max length for markdown is enough.\n</p>","metadata":{}},{"cell_type":"code","source":"title='Number of lines in code cells'\nget_token_statistics(train_df,column='cell_type',value='code',spliter='\\n',lower_percentile=10,upper_percentile=95,title=title)","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:35:57.648371Z","iopub.execute_input":"2022-06-22T15:35:57.648678Z","iopub.status.idle":"2022-06-22T15:36:08.727465Z","shell.execute_reply.started":"2022-06-22T15:35:57.648651Z","shell.execute_reply":"2022-06-22T15:36:08.726271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<p>\n    The 95<sup>th</sup> percentile is 26. Thus, most cells have less than 26 lines of code.\n</p>","metadata":{}},{"cell_type":"code","source":"max_markdown_cells=np.max(train_df[train_df['cell_type']=='markdown'].groupby('id').size())\nprint(f'max markdown cells: {max_markdown_cells}')\nmax_code_cells=np.max(train_df[train_df['cell_type']=='code'].groupby('id').size())\nprint(f'max code cells: {max_code_cells}')","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:36:08.728955Z","iopub.execute_input":"2022-06-22T15:36:08.729312Z","iopub.status.idle":"2022-06-22T15:36:12.223118Z","shell.execute_reply.started":"2022-06-22T15:36:08.729281Z","shell.execute_reply":"2022-06-22T15:36:12.221938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"markdown_cells_90=np.percentile(train_df[train_df['cell_type']=='markdown'].groupby('id').size(),90)\nprint(f'90th percentile markdown cells: {markdown_cells_90}')\ncode_cells_90=np.percentile(train_df[train_df['cell_type']=='code'].groupby('id').size(),90)\nprint(f'90th percentile code cells: {code_cells_90}')","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:36:12.224614Z","iopub.execute_input":"2022-06-22T15:36:12.224977Z","iopub.status.idle":"2022-06-22T15:36:15.713159Z","shell.execute_reply.started":"2022-06-22T15:36:12.224945Z","shell.execute_reply":"2022-06-22T15:36:15.711957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<p>\n    It seems there are a lot of cells in some notebooks. I do not expect deep learning to work well on these examples. If we use a sequential model, vanishing gradient will make it difficult for the model to learn. Sequence model do not do well for large sequences and the large sequences are just 10% of the whole dataset. Perhaps, using different techniques depending on the number of cells is best? Or maybe finding a method to concatenate cells? \n</p>\nI will check some of these notebooks:","metadata":{}},{"cell_type":"code","source":"examples_df=pd.DataFrame()\n\nfor index,group in train_df.groupby('id'):\n    if len(group)>800:\n        examples_df=pd.concat((examples_df,group))\n        \nexamples_df.to_csv('high_cardinal_examples.csv')","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:36:15.714258Z","iopub.execute_input":"2022-06-22T15:36:15.714866Z","iopub.status.idle":"2022-06-22T15:44:01.467441Z","shell.execute_reply.started":"2022-06-22T15:36:15.71483Z","shell.execute_reply":"2022-06-22T15:44:01.465919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"examples_df","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:44:01.468624Z","iopub.status.idle":"2022-06-22T15:44:01.469087Z","shell.execute_reply.started":"2022-06-22T15:44:01.46886Z","shell.execute_reply":"2022-06-22T15:44:01.46888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I preffer to download the CSV file and open it in excel. In excel I can add a table and filter by \"id\". I think it is easier than in the notebook. Although, I have added a code snippet to display the cells of a notebook below: ","metadata":{}},{"cell_type":"code","source":"demostration_df=pd.DataFrame()\nmax_number=examples_df.reset_index()['id'].nunique()\nprint(f'There are {max_number} number of cells in the notebook')\n\nexample_number=4\n\ni=1\nfor index, group in examples_df.groupby('id'):\n    if i==example_number:\n        demostration_df=group.copy()\n        break\n    i+=1\n\ncell_number=(i for i in range(0,len(demostration_df)))\ndemostration_df['source'].apply(lambda source: print(f'[cell {next(cell_number)}]',source))","metadata":{"execution":{"iopub.status.busy":"2022-06-22T15:44:01.470716Z","iopub.status.idle":"2022-06-22T15:44:01.471143Z","shell.execute_reply.started":"2022-06-22T15:44:01.470945Z","shell.execute_reply":"2022-06-22T15:44:01.470965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}