{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":116062,"databundleVersionId":14084779,"sourceType":"competition"},{"sourceId":13502493,"sourceType":"datasetVersion","datasetId":8572953},{"sourceId":269339911,"sourceType":"kernelVersion"},{"sourceId":270571028,"sourceType":"kernelVersion"},{"sourceId":270597770,"sourceType":"kernelVersion"},{"sourceId":271057791,"sourceType":"kernelVersion"}],"dockerImageVersionId":31153,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **Ensemble Submissions: Code Analysis and Explanation**\n\n## **1. Import Libraries**\n\n```python\nimport pandas as pd\n","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-28T18:55:31.721872Z","iopub.execute_input":"2025-10-28T18:55:31.722976Z","iopub.status.idle":"2025-10-28T18:55:32.145301Z","shell.execute_reply.started":"2025-10-28T18:55:31.722934Z","shell.execute_reply":"2025-10-28T18:55:32.144201Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 2. Function Definition\n\n* `ensemble_submissions:` The core function takes the following arguments:\n    * `file_paths:` A list of paths to submission files.\n    * `weights:` A list of weights used to combine the scores from the different files.\n    * `output_path:` The path where the final combined results will be saved.\n\n\n## 3. Read and Process Files\n\n\n- **File Reading:** Each file is read using `pandas.read_csv()`, which is tab-separated and has no header.\n- **Key Creation:** A new `key` column is created by combining the `protein` and `go_term`.\n- **Renaming Score Column:** The `score` column is renamed to include the file index.\n\n## 4. Merging DataFrames\n\n- **Merge:** The first file is initialized as the base result. Subsequent files are merged using the `key` column, ensuring all protein-GO term pairs are included.\n\n## 5. Handling Missing Data\n\n* **Missing Scores:** Any missing score (`NaN`) is replaced with `0` to ensure there are no missing values in the score columns.\n  \n\n## 6. Weighted Averaging of Scores\n\n* **Weighted Score Calculation:** The final score is calculated by summing the weighted scores from each file.\n  \n\n## 7. Handling Missing Protein/GO Term Data\n\n* **Filling Missing Protein/GO Term:** If any protein or GO term is missing, it is inferred from the `key` column by splitting the key string.\n\n\n## 8. Submission\n\n* **submit** the file in to the output\n\n## 9. Example Usage\n\n* **Example:** This code demonstrates how to call the function with a list of file paths and weights to generate the ensemble prediction.\n  ","metadata":{}},{"cell_type":"code","source":"# 2. Function defination\ndef load_submission(path):\n    df = pd.read_csv(path, sep='\\t', header=None)\n    df['pred_key'] = df[0].astype(str) + '_' + df[1].astype(str)\n    return df","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 3. # Takes a while\nA = load_submission('/kaggle/input/gaf-submission/submission.tsv')\nB = load_submission('/kaggle/input/merge-of-2submission-lb-0-25/submission.tsv')\n\nA_idx = A.set_index('pred_key')\nB_idx = B.set_index('pred_key')\n\ncommon_keys = A_idx.index.intersection(B_idx.index)\ncommon_ensemble = A_idx.loc[common_keys].copy()\ncommon_ensemble[2] = (A_idx.loc[common_keys, 2] + B_idx.loc[common_keys, 2]) / 2\n\nnot_common_in_A = A_idx.loc[A_idx.index.difference(common_keys)]\nnot_common_in_B = B_idx.loc[B_idx.index.difference(common_keys)]\n\nsubmission = pd.concat([common_ensemble, not_common_in_A, not_common_in_B])\nsubmission = submission.reset_index(drop=True)[[0, 1, 2]]\nsubmission.shape","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 4. Merging dataframe\n# Remove 0 scores and scores > 1\nsubmission.columns = ['ProteinID', 'GO_Term', 'Score']\nsubmission = submission[submission['Score'] >= 0.05]\nsubmission['Score'] = submission['Score'].clip(upper=1.0)\nsubmission.shape","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 5. Handling missing value\n# Keep only 1500 GO per Protein\nsubmission = (\n    submission.sort_values(['ProteinID', 'Score'], ascending=[True, False])\n    .groupby('ProteinID', group_keys=False)\n    .head(1500)\n)\nsubmission.shape","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 6.  Weighted Averaging of Scores\n# GT data collected using QuickGO API\nprotein_go_annotations = pd.read_csv('/kaggle/input/protein-go-annotations-taxonomy/protein_go_annotations.csv')\nprotein_go_annotations = protein_go_annotations[['ProteinID', 'GO_Term']]\nprotein_go_annotations['Score'] = round(1.0, 3)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 7. Handling Missing Protein/GO Term Data\ncombined = pd.concat([submission, protein_go_annotations], ignore_index=True)\n\n# Drop duplicates,\n# Keep the ground truth score (1.0) if overlap\ncombined.sort_values(by='Score', ascending=False, inplace=True)\nfinal_submission = combined.drop_duplicates(subset=['ProteinID', 'GO_Term'], keep='first').reset_index(drop=True)\nfinal_submission.shape","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 8. Submission\nfinal_submission.to_csv('submission.tsv',sep='\\t', index=False, header=None)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Conclusion\n\nThis script provides a method for combining multiple protein-GO term prediction files into a single, weighted ensemble. It handles missing data gracefully, merges files efficiently, and outputs the final sorted results for downstream analysis.","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n# # 2. Function Definition\n# # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n# def ensemble_submissions(file_paths, weights, output_path='submission.tsv'):\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     # 3. Read and Process Files\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     dfs = []\n#     for i, path in enumerate(file_paths):\n#         df = pd.read_csv(path, sep='\\t', header=None, names=['protein', 'go_term', 'score'])\n#         df['key'] = df['protein'] + '_' + df['go_term']\n#         df = df.rename(columns={'score': f'score_{i}'})\n#         dfs.append(df)\n#         print(f\"Loaded {len(df)} predictions from file {i+1}\")\n\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     ## 4. Merging DataFrames\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     result = dfs[0][['protein', 'go_term', 'key', 'score_0']].copy()\n#     for i in range(1, len(dfs)):\n#         result = result.merge(dfs[i][['key', f'score_{i}']], on='key', how='outer')\n\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     #  5. Handling Missing Data\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     for i in range(len(dfs)):\n#         result[f'score_{i}'] = result[f'score_{i}'].fillna(0)\n\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     # 6. Weighted Averaging of Scores\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     result['score'] = sum(weights[i] * result[f'score_{i}'] for i in range(len(dfs)))\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     # 7. Handling Missing Protein/GO Term Data\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     result['protein'] = result['protein'].fillna(result['key'].str.split('_').str[0])\n#     result['go_term'] = result['go_term'].fillna(result['key'].str.split('_').str[-1])\n\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     # 8. Sorting and Saving Final Predictions\n#     # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n#     result = result.sort_values('score', ascending=False)\n#     result[['protein', 'go_term', 'score']].to_csv(\n#         output_path,\n#         sep='\\t',\n#         index=False,\n#         header=False\n#     )\n    \n#     print(f\"\\nSaved {len(result)} predictions to {output_path}\")\n#     return result\n# # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n# # 9. Example Usage\n# # -=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-=_=-\n# if __name__ == \"__main__\":\n#     file_paths = [\n#         '/kaggle/input/cafa-6-protein-function-prediction'\n#         # '/kaggle/input/gaf-submission/submission.tsv',\n#         # '/kaggle/input/cafa-6-predictions/submission.tsv'\n#     ]\n#     weights = [0.5, 0.5]\n    \n#     ensemble_submissions(file_paths, weights)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-28T18:59:23.549912Z","iopub.execute_input":"2025-10-28T18:59:23.550984Z","iopub.status.idle":"2025-10-28T18:59:23.586552Z","shell.execute_reply.started":"2025-10-28T18:59:23.550951Z","shell.execute_reply":"2025-10-28T18:59:23.585363Z"}},"outputs":[],"execution_count":null}]}