{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":1882037,"sourceType":"datasetVersion","datasetId":1120859}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **Student Info**\n\n# Chinese Name: 郭卜玮\n\n# Pinyin:Guo BoWei\n\n# English Name: Johnson\n\n# Student Number: 2202520302018\n\nI swear that the contents of this notebook (apart from the dataset) are entirely\nmy own work. There is no AI generated code, text, or otherwise, and I have not\ncopied the work of any other students or anyone else. I understand that a breach\nof this promise will result in an immediate fail.\n\nhttps://www.kaggle.com/code/johnsonjob/dsml-2-18","metadata":{}},{"cell_type":"markdown","source":"# **Introduction**\nThe dataset selected for this project is the stroke prediction dataset. This dataset contains a lot of comprehensive health information of patients to predict the possibility of stroke in the experimental subjects. The main reason why I chose this dataset is that I think stroke is a very serious disease. If it can be predicted earlier, timely treatment can be carried out to reduce the number of patients. Contribute to the progress of medicine.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\ndf = pd.read_csv(\"/kaggle/input/stroke-prediction-dataset/healthcare-dataset-stroke-data.csv\")\ndf.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:21.623908Z","iopub.execute_input":"2025-06-09T00:24:21.624246Z","iopub.status.idle":"2025-06-09T00:24:22.086037Z","shell.execute_reply.started":"2025-06-09T00:24:21.624219Z","shell.execute_reply":"2025-06-09T00:24:22.084953Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Cleaning**\nAmong the numerous data, there are many missing values, outliers and invalid items. In order to better predict and build the model, I choose to start data cleaning first.","metadata":{}},{"cell_type":"markdown","source":"**Data loading.** First, we import the libraries we need, pandas and numpy. One is used to handle tabular data, and numpy is used for reasonable scientific calculations. And reading the data inside will help me build the model.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\n\npd.set_option('display.max_columns', None)\n\n\ndf = pd.read_csv(\"/kaggle/input/stroke-prediction-dataset/healthcare-dataset-stroke-data.csv\")\n\nprint(\" Data sample (the first 5 lines)：\")\ndisplay(df.head())\n\nprint(f\"\\n The number of rows and columns of the dataset: {df.shape[0]} , {df.shape[1]} \")\n\nprint(\"\\n All the column names：\")\nprint(df.columns.tolist())\n\nprint(\"\\n The data type and the number of non-null values in each column：\")\nprint(df.info())\n\nprint(\"\\n Statistical information of numerical characteristics：\")\ndisplay(df.describe())\n\nprint(\"\\n The number of missing values in each column：\")\nprint(df.isnull().sum())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:22.087322Z","iopub.execute_input":"2025-06-09T00:24:22.087686Z","iopub.status.idle":"2025-06-09T00:24:22.168159Z","shell.execute_reply.started":"2025-06-09T00:24:22.087661Z","shell.execute_reply":"2025-06-09T00:24:22.167224Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"After the operation was completed, I got a general understanding of the structure of the dataset I chose, the data types, which was beneficial for my data cleaning.","metadata":{}},{"cell_type":"markdown","source":"**Handling of missing values.** After the above operations, what I need to do now is to count the number of missing values and handle them.","metadata":{}},{"cell_type":"code","source":"print(\"The number of missing values in each row: \")\ndf.isnull().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:22.169963Z","iopub.execute_input":"2025-06-09T00:24:22.170212Z","iopub.status.idle":"2025-06-09T00:24:22.180183Z","shell.execute_reply.started":"2025-06-09T00:24:22.170191Z","shell.execute_reply":"2025-06-09T00:24:22.179071Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"It is learned from the statistics here that it seems only the BMI column has missing values","metadata":{}},{"cell_type":"markdown","source":"Here, I have no idea what the BMI data values are like, so I choose to visualize the BMI data first to better select the method for handling the missing values.","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\nplt.figure(figsize=(8, 5))\nsns.histplot(df['bmi'], kde=True, bins=30, color='skyblue')\nplt.title('BMI distribution map')\nplt.xlabel('BMI')\nplt.ylabel('Frequency')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:22.181794Z","iopub.execute_input":"2025-06-09T00:24:22.182075Z","iopub.status.idle":"2025-06-09T00:24:23.514939Z","shell.execute_reply.started":"2025-06-09T00:24:22.182052Z","shell.execute_reply":"2025-06-09T00:24:23.513916Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"After the operation, I obtained a graph like a normal distribution","metadata":{}},{"cell_type":"markdown","source":"Looking at this graph, I think it is a normal distribution graph. Therefore, I believe that the mean value should be used to fill in the missing values, because the mean value can accurately represent the center of the data. A small amount of data that is too large or too small will not cause a large deviation to the whole, and can maintain the symmetry of the original data and the overall trend.After filling with the mean value, casually check if there are any that are still missing.","metadata":{}},{"cell_type":"code","source":"mean_bmi = df[\"bmi\"].mean()\ndf[\"bmi\"].fillna(mean_bmi, inplace=True)\n\ndf.isnull().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:23.516094Z","iopub.execute_input":"2025-06-09T00:24:23.516689Z","iopub.status.idle":"2025-06-09T00:24:23.529121Z","shell.execute_reply.started":"2025-06-09T00:24:23.516649Z","shell.execute_reply":"2025-06-09T00:24:23.527906Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Facts have proved that I have completed the data cleaning.","metadata":{}},{"cell_type":"markdown","source":"**In summary**\nIn the above operations, I completed the cleaning of the data to ensure that my subsequent modeling and analysis were not hindered by missing data.","metadata":{}},{"cell_type":"markdown","source":"# **Visualization**\n\nAt this stage, I will use data visualization to analyze various relationships of the data and the connections between the data and stroke, providing support for subsequent modeling.","metadata":{}},{"cell_type":"markdown","source":"I think we should first learn about the situation of stroke.","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\nsns.set(style=\"whitegrid\")\n\nplt.figure(figsize=(6, 4))\nsns.countplot(data=df, x='stroke', palette='pastel')\nplt.title(\"Stroke Distribution\")\nplt.xlabel(\"Stroke (0 = No, 1 = Yes)\")\nplt.ylabel(\"Number of People\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:23.530114Z","iopub.execute_input":"2025-06-09T00:24:23.530431Z","iopub.status.idle":"2025-06-09T00:24:23.712684Z","shell.execute_reply.started":"2025-06-09T00:24:23.530405Z","shell.execute_reply":"2025-06-09T00:24:23.711693Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Obviously, the number of people suffering from strokes is not large.","metadata":{}},{"cell_type":"markdown","source":"Next, let's study the influence of age on stroke.","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\nplt.figure(figsize=(8, 5))\nsns.histplot(data=df, x='age', hue='stroke', kde=True, bins=30, palette='Set2')\nplt.title(\"Relationship Between Age and Stroke\")\nplt.xlabel(\"Age\")\nplt.ylabel(\"Number of People\")\nplt.legend(title='Stroke Status', labels=['No', 'Yes'])\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:23.713661Z","iopub.execute_input":"2025-06-09T00:24:23.713913Z","iopub.status.idle":"2025-06-09T00:24:24.140104Z","shell.execute_reply.started":"2025-06-09T00:24:23.713892Z","shell.execute_reply":"2025-06-09T00:24:24.139055Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Stroke occurs more frequently in older groups, especially among those over 60 years old, whose incidence is significantly higher than that of young people. It can be seen from this that the influence of age is an important parameter.","metadata":{}},{"cell_type":"markdown","source":"The influence of gender on stroke。","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(6, 4))\nsns.countplot(data=df, x='gender', hue='stroke', palette='Set1')\nplt.title(\"Relationship Between Gender and Stroke\")\nplt.xlabel(\"Gender\")\nplt.ylabel(\"Number of People\")\nplt.legend(title=\"Stroke Status\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:24.142875Z","iopub.execute_input":"2025-06-09T00:24:24.143186Z","iopub.status.idle":"2025-06-09T00:24:24.366672Z","shell.execute_reply.started":"2025-06-09T00:24:24.143159Z","shell.execute_reply":"2025-06-09T00:24:24.365622Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The data shows that the impact seems not significant.","metadata":{}},{"cell_type":"markdown","source":"The Relationship Between Hypertension and Stroke.","metadata":{}},{"cell_type":"code","source":"htn_ct = pd.crosstab(df['hypertension'], df['stroke'], normalize='index') * 100\nhtn_ct.columns = ['No Stroke', 'Stroke']\nhtn_ct.index = ['No Hypertension', 'Hypertension']\n\nhtn_ct.plot(kind='bar', stacked=True, colormap='Reds', figsize=(6, 5))\nplt.title(\"Relationship Between Hypertension and Stroke (Percentage)\")\nplt.ylabel(\"Percentage (%)\")\nplt.xlabel(\"Hypertension\")\nplt.legend(title=\"Stroke Status\", loc=\"upper right\")\nplt.ylim(0, 100)\n\nfor i, row in enumerate(htn_ct.values):\n    plt.text(i, row[0]/2, f'{row[0]:.1f}%', ha='center')\n    plt.text(i, 100 - row[1]/2, f'{row[1]:.1f}%', ha='center', color='white')\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:24.368225Z","iopub.execute_input":"2025-06-09T00:24:24.368482Z","iopub.status.idle":"2025-06-09T00:24:24.691047Z","shell.execute_reply.started":"2025-06-09T00:24:24.368460Z","shell.execute_reply":"2025-06-09T00:24:24.689801Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The relationship between heart disease and stroke.","metadata":{}},{"cell_type":"code","source":"heart_ct = pd.crosstab(df['heart_disease'], df['stroke'], normalize='index') * 100\nheart_ct.columns = ['No Stroke', 'Stroke']\nheart_ct.index = ['No Heart Disease', 'Has Heart Disease']\n\nheart_ct.plot(kind='bar', stacked=True, colormap='Oranges', figsize=(6, 5))\nplt.title(\"Relationship between Heart Disease and Stroke (Percentage)\")\nplt.ylabel(\"Percentage (%)\")\nplt.xlabel(\"Heart Disease Status\")\nplt.legend(title=\"Stroke Status\")\nplt.ylim(0, 100)\n\nfor i, row in enumerate(heart_ct.values):\n    plt.text(i, row[0]/2, f'{row[0]:.1f}%', ha='center')\n    plt.text(i, 100 - row[1]/2, f'{row[1]:.1f}%', ha='center', color='white')\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:24.692068Z","iopub.execute_input":"2025-06-09T00:24:24.692326Z","iopub.status.idle":"2025-06-09T00:24:25.048665Z","shell.execute_reply.started":"2025-06-09T00:24:24.692304Z","shell.execute_reply":"2025-06-09T00:24:25.047621Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Data shows that there is no doubt that people with hypertension and heart disease are more likely to have a stroke.","metadata":{}},{"cell_type":"markdown","source":"The relationship between Ever Married and Stroke.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(5, 4))\nsns.countplot(x='ever_married', hue='stroke', data=df)\nplt.title('Relationship Between Marital Status and Stroke')\nplt.xlabel('Marital Status')\nplt.ylabel('Number of People')\nplt.legend(title='Stroke')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:25.049829Z","iopub.execute_input":"2025-06-09T00:24:25.050216Z","iopub.status.idle":"2025-06-09T00:24:25.258049Z","shell.execute_reply.started":"2025-06-09T00:24:25.050178Z","shell.execute_reply":"2025-06-09T00:24:25.257025Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"It seems that those who get married are more likely to have a stroke.","metadata":{}},{"cell_type":"markdown","source":"The relationship between job types and stroke.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(6, 4))\nsns.countplot(x='work_type', hue='stroke', data=df)\nplt.title('Work Type and Stroke')\nplt.xlabel('Work Type')\nplt.ylabel('Number of People')\nplt.xticks(rotation=30)\nplt.legend(title='Stroke')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:25.259113Z","iopub.execute_input":"2025-06-09T00:24:25.259377Z","iopub.status.idle":"2025-06-09T00:24:25.505819Z","shell.execute_reply.started":"2025-06-09T00:24:25.259355Z","shell.execute_reply":"2025-06-09T00:24:25.504673Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The relationship between place of residence and stroke.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(5, 4))\nsns.countplot(x='Residence_type', hue='stroke', data=df)\nplt.title('Residence Type and Stroke')\nplt.xlabel('Urban/Rural')\nplt.ylabel('Number of People')\nplt.legend(title='Stroke')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:25.506897Z","iopub.execute_input":"2025-06-09T00:24:25.507234Z","iopub.status.idle":"2025-06-09T00:24:25.708342Z","shell.execute_reply.started":"2025-06-09T00:24:25.507194Z","shell.execute_reply":"2025-06-09T00:24:25.707287Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The relationship between smoking status and stroke.","metadata":{}},{"cell_type":"code","source":"smoke_ct = pd.crosstab(df['smoking_status'], df['stroke'], normalize='index') * 100\nsmoke_ct.columns = ['No Stroke', 'Stroke']\n\nsmoke_ct.plot(kind='bar', stacked=True, colormap='Greens', figsize=(8, 5))\nplt.title(\"Relationship between Smoking Status and Stroke (Percentage)\")\nplt.ylabel(\"Percentage (%)\")\nplt.xlabel(\"Smoking Status\")\nplt.xticks(rotation=45)\nplt.legend(title=\"Stroke Status\")\nplt.ylim(0, 100)\n\nfor i, row in enumerate(smoke_ct.values):\n    plt.text(i, row[0]/2, f'{row[0]:.1f}%', ha='center', fontsize=8)\n    plt.text(i, 100 - row[1]/2, f'{row[1]:.1f}%', ha='center', color='white', fontsize=8)\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:25.709324Z","iopub.execute_input":"2025-06-09T00:24:25.709615Z","iopub.status.idle":"2025-06-09T00:24:26.029922Z","shell.execute_reply.started":"2025-06-09T00:24:25.709591Z","shell.execute_reply":"2025-06-09T00:24:26.028812Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"There is no doubt that people who smoke ordinarily and frequently have a greater probability of stroke.","metadata":{}},{"cell_type":"markdown","source":"Relationship Between Average Glucose Level and Stroke.","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.simplefilter(action='ignore', category=FutureWarning)\nplt.figure(figsize=(8, 5))\nsns.kdeplot(data=df, x=\"avg_glucose_level\", hue=\"stroke\", fill=True, common_norm=False, palette=\"coolwarm\", alpha=0.5)\nplt.title(\"Relationship Between Average Glucose Level and Stroke\")\nplt.xlabel(\"Average Glucose Level\")\nplt.ylabel(\"Density\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.030920Z","iopub.execute_input":"2025-06-09T00:24:26.031187Z","iopub.status.idle":"2025-06-09T00:24:26.392945Z","shell.execute_reply.started":"2025-06-09T00:24:26.031165Z","shell.execute_reply":"2025-06-09T00:24:26.391880Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"People with high blood sugar have an increased risk of stroke.","metadata":{}},{"cell_type":"markdown","source":"The relationship between BMI and stroke.","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\nplt.figure(figsize=(8, 5))\nsns.boxplot(data=df, x='stroke', y='bmi', palette='Set2')\nplt.title(\"Relationship between BMI and Stroke (Boxplot)\")\nplt.xlabel(\"Stroke (0 = No, 1 = Yes)\")\nplt.ylabel(\"Body Mass Index (BMI)\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.394209Z","iopub.execute_input":"2025-06-09T00:24:26.394643Z","iopub.status.idle":"2025-06-09T00:24:26.582762Z","shell.execute_reply.started":"2025-06-09T00:24:26.394606Z","shell.execute_reply":"2025-06-09T00:24:26.581730Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"People with a high BMI have a greater risk of stroke.","metadata":{}},{"cell_type":"markdown","source":"**The summary is as follows:**\n\n1. People with a history of hypertension and heart disease have a higher risk of stroke.\n2. Among married people, the number of stroke cases is relatively high.\n3. People with high blood sugar have an increased risk of stroke.\n4. here is little difference in the proportion of stroke between urban and rural residents.\n5. When BMI is higher, the probability of stroke increases to a certain extent.\n6. Smokers (especially former smokers) have a slightly higher number of strokes.\n","metadata":{}},{"cell_type":"markdown","source":"# **Feature Engineering**\n\nIn this part, my main task is to delete irrelevant data, categorize and edit variable information, standardize the information of numerical types, and lay a solid foundation for my subsequent modeling.","metadata":{}},{"cell_type":"markdown","source":"Among all the predicted data, the ID column is of no use at all, so the ID column needs to be deleted.","metadata":{}},{"cell_type":"code","source":"df = df.drop(columns=['id'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.583943Z","iopub.execute_input":"2025-06-09T00:24:26.584302Z","iopub.status.idle":"2025-06-09T00:24:26.590340Z","shell.execute_reply.started":"2025-06-09T00:24:26.584268Z","shell.execute_reply":"2025-06-09T00:24:26.589196Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.591344Z","iopub.execute_input":"2025-06-09T00:24:26.591683Z","iopub.status.idle":"2025-06-09T00:24:26.619763Z","shell.execute_reply.started":"2025-06-09T00:24:26.591657Z","shell.execute_reply":"2025-06-09T00:24:26.618732Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The \"ID\" column has been deleted.","metadata":{}},{"cell_type":"markdown","source":"Because machine learning cannot accept features of string type, it is necessary to encode these features that cannot be used for machine learning. df_encoded is a numerical DataFrame. All the specified categorical variables are converted into 0/1 values and can be directly used for model training or feature analysis.","metadata":{}},{"cell_type":"code","source":"categorical_cols = ['gender', 'ever_married', 'work_type', 'Residence_type', 'smoking_status']\ndf_encoded = pd.get_dummies(df, columns=categorical_cols, drop_first=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.620890Z","iopub.execute_input":"2025-06-09T00:24:26.621276Z","iopub.status.idle":"2025-06-09T00:24:26.643094Z","shell.execute_reply.started":"2025-06-09T00:24:26.621238Z","shell.execute_reply":"2025-06-09T00:24:26.642059Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(df_encoded.columns)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.644096Z","iopub.execute_input":"2025-06-09T00:24:26.644441Z","iopub.status.idle":"2025-06-09T00:24:26.650659Z","shell.execute_reply.started":"2025-06-09T00:24:26.644406Z","shell.execute_reply":"2025-06-09T00:24:26.649779Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"It has now been proved that the hot coding has been completed.","metadata":{}},{"cell_type":"markdown","source":"Some special models have higher requirements. To avoid log(0) errors, reduce the right-biased distribution, and narrow the gap between extreme values, the distribution of numerical variables is processed.","metadata":{}},{"cell_type":"code","source":"import numpy as np\n\ndf_encoded['avg_glucose_level'] = np.log1p(df_encoded['avg_glucose_level'])\ndf_encoded['bmi'] = np.log1p(df_encoded['bmi'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.651628Z","iopub.execute_input":"2025-06-09T00:24:26.651877Z","iopub.status.idle":"2025-06-09T00:24:26.670083Z","shell.execute_reply.started":"2025-06-09T00:24:26.651856Z","shell.execute_reply":"2025-06-09T00:24:26.669175Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_encoded[['avg_glucose_level', 'bmi']].describe()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.671067Z","iopub.execute_input":"2025-06-09T00:24:26.671403Z","iopub.status.idle":"2025-06-09T00:24:26.695561Z","shell.execute_reply.started":"2025-06-09T00:24:26.671371Z","shell.execute_reply":"2025-06-09T00:24:26.694385Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The logarithmic transformation of avg_glucose_level and bmi has been successfully completed!","metadata":{}},{"cell_type":"markdown","source":"To conduct model training, we divide the data into two parts:\n\n- 'X' : All feature variables (removing the target column 'stroke')\n- 'y' : The target variable 'stroke', representing whether the user has ever had a stroke (0 indicates no, 1 indicates yes)","metadata":{}},{"cell_type":"code","source":"X = df_encoded.drop('stroke', axis=1)\ny = df_encoded['stroke']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.699446Z","iopub.execute_input":"2025-06-09T00:24:26.699780Z","iopub.status.idle":"2025-06-09T00:24:26.706217Z","shell.execute_reply.started":"2025-06-09T00:24:26.699756Z","shell.execute_reply":"2025-06-09T00:24:26.704933Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"X shape:\", X.shape)\nprint(\"y shape:\", y.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.707644Z","iopub.execute_input":"2025-06-09T00:24:26.708008Z","iopub.status.idle":"2025-06-09T00:24:26.730328Z","shell.execute_reply.started":"2025-06-09T00:24:26.707967Z","shell.execute_reply":"2025-06-09T00:24:26.729404Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"It's been successfully completed. Now we can move on to the next part.","metadata":{}},{"cell_type":"markdown","source":"# **Prediction**\n\nWhat I need to do in the prediction part is to establish a basic regression model to achieve the experimental purpose I mentioned.","metadata":{}},{"cell_type":"markdown","source":"I divided the data into the training set and the test set in an 80%/20% ratio.","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\n\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n\n\nprint(\"Training set X:\", X_train.shape)\nprint(\"Test set X:\", X_test.shape)\nprint(\"Training set y:\", y_train.shape)\nprint(\"Test set y:\", y_test.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.731196Z","iopub.execute_input":"2025-06-09T00:24:26.731561Z","iopub.status.idle":"2025-06-09T00:24:26.938904Z","shell.execute_reply.started":"2025-06-09T00:24:26.731534Z","shell.execute_reply":"2025-06-09T00:24:26.937765Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"At the very beginning, I imported multiple evaluation metrics of the model, such as accuracy rate, precision rate, recall rate, F1 score, confusion matrix, and comprehensive reports, to measure the performance of the classification model and imported a logistic regression class to determine whether there was a stroke.","metadata":{}},{"cell_type":"code","source":"from sklearn.linear_model import LogisticRegression\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:26.939943Z","iopub.execute_input":"2025-06-09T00:24:26.940217Z","iopub.status.idle":"2025-06-09T00:24:27.043271Z","shell.execute_reply.started":"2025-06-09T00:24:26.940183Z","shell.execute_reply":"2025-06-09T00:24:27.042281Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Create a logistic regression model object model. Set the maximum number of iterations to 1000 random seeds to ensure consistent results at each run. Use the training data X_train and y_train to train the model.class_weight='balanced' : Automatically adjust the weights of different categories to solve the problem of category imbalance.","metadata":{}},{"cell_type":"code","source":"model = LogisticRegression(max_iter=1000, random_state=42, class_weight='balanced')\nmodel.fit(X_train, y_train)\ny_pred = model.predict(X_test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:27.044107Z","iopub.execute_input":"2025-06-09T00:24:27.044362Z","iopub.status.idle":"2025-06-09T00:24:27.182955Z","shell.execute_reply.started":"2025-06-09T00:24:27.044341Z","shell.execute_reply":"2025-06-09T00:24:27.182089Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The initialization of the model has now been completed. ","metadata":{}},{"cell_type":"markdown","source":"Next, predict the test set.","metadata":{}},{"cell_type":"code","source":"y_pred = model.predict(X_test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:27.183894Z","iopub.execute_input":"2025-06-09T00:24:27.184273Z","iopub.status.idle":"2025-06-09T00:24:27.191103Z","shell.execute_reply.started":"2025-06-09T00:24:27.184239Z","shell.execute_reply":"2025-06-09T00:24:27.189957Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"acc = accuracy_score(y_test, y_pred)\nprec = precision_score(y_test, y_pred)\nrec = recall_score(y_test, y_pred)\nf1 = f1_score(y_test, y_pred)\n\nprint(f\"Accuracy: {acc:.4f}\")\nprint(f\"Precision: {prec:.4f}\")\nprint(f\"Recall: {rec:.4f}\")\nprint(f\"F1 Score: {f1:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T00:24:27.192100Z","iopub.execute_input":"2025-06-09T00:24:27.192371Z","iopub.status.idle":"2025-06-09T00:24:27.219170Z","shell.execute_reply.started":"2025-06-09T00:24:27.192348Z","shell.execute_reply":"2025-06-09T00:24:27.218053Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The model showed a high recall rate (approximately 79%) on the test set, indicating that most stroke patients were successfully identified. This is very important for medical risk early warning and can effectively reduce missed diagnoses. However, the accuracy rate of the model is relatively low. This model is suitable as an initial screening tool for the risk of stroke.","metadata":{}},{"cell_type":"markdown","source":"# **Conclusion**\n\nThe dataset I chose contains 5,110 records and has 12 columns. The target variable is whether one has suffered a stroke. The numerical variables age, avg_glucose_level and bmi show a certain influence on the probability of stroke. Other variables also have a certain influence. In terms of data cleaning and preprocessing, I dealt with the missing values of bmi, filled them with the mean, and converted all category variables into numerical forms. The numerical variables were normalized to unify the data scale. In the visualization exploration section, I utilized various graphs to analyze the relationship between stroke and all related factors. Regarding model selection: I employed a simple logistic regression model and enabled class_weight='balanced' to address the issue of too few stroke samples. \n\nPerformance Evaluation:\n\nAccuracy: Approximately 74.9%\n\nPrecision: Approximately 16.8%\n\nRecall rate: Approximately 79.0%\n\nF1 Score: Approximately 27.7%. \n\nHowever, the accuracy rate is relatively low and there is a risk of false alarms.The results show that this model can effectively identify the majority of stroke patients, with a high recall rate, and is suitable for use in medical early warning systems.","metadata":{}}]}