From e5eb41566323e2714722a4eaca1f2591cf84fff3 Mon Sep 17 00:00:00 2001
From: Margaret Awojide <49078266+awojidetola@users.noreply.github.com>
Date: Tue, 17 Oct 2023 10:37:20 +0100
Subject: [PATCH 1/8] Create README.MD
---
Project_3/GPA_Prediction_awojidetola/README.MD | 1 +
1 file changed, 1 insertion(+)
create mode 100644 Project_3/GPA_Prediction_awojidetola/README.MD
diff --git a/Project_3/GPA_Prediction_awojidetola/README.MD b/Project_3/GPA_Prediction_awojidetola/README.MD
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/Project_3/GPA_Prediction_awojidetola/README.MD
@@ -0,0 +1 @@
+
From f414c5f6fad8f88eb03f3118967de3bba6aac70f Mon Sep 17 00:00:00 2001
From: Margaret Awojide <49078266+awojidetola@users.noreply.github.com>
Date: Tue, 17 Oct 2023 10:45:14 +0100
Subject: [PATCH 2/8] Add files via upload
---
.../GPA_Prediction.ipynb | 356 ++++++++++++++++++
1 file changed, 356 insertions(+)
create mode 100644 Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
diff --git a/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb b/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
new file mode 100644
index 00000000..871ca736
--- /dev/null
+++ b/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
@@ -0,0 +1,356 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "68c4d65d",
+ "metadata": {},
+ "source": [
+ "# GPA Prediction Starter Notebook\n",
+ "\n",
+ "Welcome to the GPA Prediction Starter Notebook for our project! 🚀\n",
+ "\n",
+ "In this notebook, you'll find a ready-to-use Python script that provides a solid foundation for building a GPA predictor based on the data from `year1_gpa.csv`.\n",
+ "\n",
+ "## Getting Started\n",
+ "\n",
+ "To get started, follow these steps:\n",
+ "\n",
+ "1. **Clone the Repository**: Begin by cloning this repository to your local machine.\n",
+ "\n",
+ "2. **Organize Your Data**: Ensure that your GPA data is organized in the `Data` directory, particularly the `year1_gpa.csv` file.\n",
+ "\n",
+ "3. **Open the Notebook**: Open this notebook in a Jupyter environment.\n",
+ "\n",
+ "4. **Follow the Code**: The notebook contains commented code that guides you through the process of setting up the data, building and training the model, and evaluating its performance.\n",
+ "\n",
+ "5. **Experiment and Contribute**: Feel free to experiment with different models,engineering features, hyperparameters, or preprocessing techniques. If you come up with improvements, consider contributing them back to the project!\n",
+ "\n",
+ "## Important Notes\n",
+ "\n",
+ "- Ensure that you have the necessary Python libraries, such as Pandas, NumPy, and scikit-learn, installed in your environment.\n",
+ "- If you encounter any issues or have questions, don't hesitate to reach out. We're here to help!\n",
+ "\n",
+ "Happy coding, and let's build an amazing GPA predictor together! \n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6ee4356f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Import necessary libraries\n",
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.linear_model import LinearRegression\n",
+ "from sklearn.metrics import mean_squared_error\n",
+ "from sklearn.preprocessing import OrdinalEncoder, LabelEncoder\n",
+ "import warnings\n",
+ "import joblib\n",
+ "# Set display options to show all columns\n",
+ "pd.set_option('display.max_columns', None)\n",
+ "\n",
+ "# Ignore warnings\n",
+ "warnings.filterwarnings('ignore')\n",
+ "print(\"Importation complete\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ea57f719",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Load the GPA data from year1_gpa.csv\n",
+ "data_path = \"Data\\year1_gpa.csv\" # Adjust the path as needed\n",
+ "gpa_data = pd.read_csv(data_path,encoding='latin1')\n",
+ "gpa_data.columns\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6f2fa180",
+ "metadata": {},
+ "source": [
+ "## Data Preprocessing\n",
+ "In the preprocessing stage, we carefully handle the GPA dataset by addressing missing values, performing feature engineering, and ensuring uniform data formatting to prepare it for accurate model training and prediction."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "319ebe42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "\n",
+ "# Dictionary to map old column names to new names\n",
+ "new_column_names = {\n",
+ " 'ID': 'id',\n",
+ " 'Start time': 'start_time',\n",
+ " 'Completion time': 'completion_time',\n",
+ " 'Email': 'email',\n",
+ " 'Name': 'name',\n",
+ " 'Last modified time': 'last_modified_time',\n",
+ " 'Jamb score': 'jamb_score',\n",
+ " 'English': 'english',\n",
+ " 'Maths': 'maths',\n",
+ " 'Subject 3': 'subject_3',\n",
+ " 'Subject 4': 'subject_4',\n",
+ " 'Subject 5': 'subject_5',\n",
+ " 'What was your age in Year One': 'age_in_year_one',\n",
+ " 'Gender': 'gender',\n",
+ " 'Do you have a disability?': 'has_disability',\n",
+ " 'Did you attend extra tutorials? ': 'attended_tutorials',\n",
+ " 'How would you rate your participation in extracurricular activities (tech, music, partying, fellowship, etc.) in Year One?': 'extracurricular_participation',\n",
+ " 'How would you rate your class attendance in Year One': 'class_attendance_rating',\n",
+ " 'How well did you participate in class activities (Assignments, Asking and Answering Questions, Writing Notes....)': 'class_participation_rating',\n",
+ " 'Did you use extra materials for study in Year One? (Youtube, Other books, others)': 'used_extra_study_materials',\n",
+ " 'Morning': 'morning_study',\n",
+ " 'Afternoon': 'afternoon_study',\n",
+ " 'Evening': 'evening_study',\n",
+ " 'Late Night': 'late_night_study',\n",
+ " 'How many days per week did you do reading on average in Year One?': 'days_per_week_reading',\n",
+ " 'On average, How many hours per day was used for personal study in Year One': 'hours_per_day_personal_study',\n",
+ " 'Did you teach your peers in Year One': 'taught_peers',\n",
+ " 'How many courses did you offer in Year One?': 'courses_offered',\n",
+ " 'Did you fall sick in Year One? if yes, How many times do you remember (0 if none)': 'times_fell_sick',\n",
+ " 'What was your study mode in Year 1': 'study_mode',\n",
+ " 'Did you study the course your originally applied for?': 'studied_original_course',\n",
+ " 'Rate your financial status in Year One': 'financial_status_rating',\n",
+ " 'Rate the teaching style / method of the lectures received in Year One': 'teaching_style_rating',\n",
+ " 'What type of higher institution did you attend in Year One\\n': 'institution_type',\n",
+ " 'What was your CGPA in Year One?': 'cgpa_year_one',\n",
+ " 'What grading system does your school use ( if others, type numbers only)': 'grading_system'\n",
+ "}\n",
+ "\n",
+ "# Rename columns using the dictionary\n",
+ "gpa_data.rename(columns=new_column_names, inplace=True)\n",
+ "\n",
+ "# Print the DataFrame with updated column names\n",
+ "gpa_data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9607b662",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# List of columns to drop\n",
+ "columns_to_drop = ['start_time', 'completion_time', 'email', 'name', 'last_modified_time']\n",
+ "\n",
+ "# Drop the specified columns\n",
+ "gpa_data.drop(columns=columns_to_drop, inplace=True)\n",
+ "\n",
+ "# Print the DataFrame after dropping columns\n",
+ "gpa_data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "74b3bddd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Separate columns into numeric and categorical\n",
+ "numeric_columns = gpa_data.select_dtypes(include=[np.number]).columns.tolist()\n",
+ "categorical_columns = gpa_data.select_dtypes(include=[np.object]).columns.tolist()\n",
+ "\n",
+ "# Print the lists\n",
+ "print(\"Numeric Columns:\")\n",
+ "print(numeric_columns)\n",
+ "\n",
+ "print(\"\\nCategorical Columns:\")\n",
+ "print(categorical_columns)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "82ff069e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "\n",
+ "# Ordinal encoding map\n",
+ "ordinal_encoding_map = {'A': 5, 'B': 4, 'C': 3, 'D': 2, 'E': 1, 'F': 0}\n",
+ "\n",
+ "# Features to encode\n",
+ "features_to_encode = ['english', 'maths', 'subject_3', 'subject_4', 'subject_5']\n",
+ "\n",
+ "# Apply ordinal encoding for the specified features\n",
+ "gpa_data[features_to_encode] = gpa_data[features_to_encode].apply(lambda col: col.map(ordinal_encoding_map))\n",
+ "\n",
+ "# Perform label encoding for other categorical columns\n",
+ "categorical_columns = gpa_data.select_dtypes(include=['object']).columns\n",
+ "label_encoder = LabelEncoder()\n",
+ "\n",
+ "for col in categorical_columns:\n",
+ " gpa_data[col] = label_encoder.fit_transform(gpa_data[col])\n",
+ "\n",
+ "# Create GPA_normal and drop unnecessary columns\n",
+ "gpa_data['GPA_normal'] = gpa_data['cgpa_year_one'] / gpa_data['grading_system']\n",
+ "gpa_data.drop(['grading_system', 'cgpa_year_one'], axis=1, inplace=True)\n",
+ "\n",
+ "\n",
+ "# Print the DataFrame after engineering\n",
+ "gpa_data\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "956dd850",
+ "metadata": {},
+ "source": [
+ "## Machine Learning Modeling\n",
+ "\n",
+ "In this section, we will walk through the steps involved in building and evaluating a machine learning model for our GPA prediction task.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4803d47f",
+ "metadata": {},
+ "source": [
+ "### Model Training"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "99913bf8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X = gpa_data.drop(['id', 'GPA_normal'], axis=1) # Features excluding 'id' and 'GPA_normal'\n",
+ "y = gpa_data['GPA_normal'] # Target variable\n",
+ "\n",
+ "# Train-test split\n",
+ "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n",
+ "\n",
+ "# Initialize the Linear Regression model\n",
+ "model = LinearRegression()\n",
+ "\n",
+ "# Train the model\n",
+ "model.fit(X_train, y_train)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ab53c71a",
+ "metadata": {},
+ "source": [
+ "### Model Evaluation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9c958bb3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Predict on the test set\n",
+ "y_pred = model.predict(X_test)\n",
+ "\n",
+ "# Evaluate the model\n",
+ "rmse = mean_squared_error(y_test, y_pred, squared=False)\n",
+ "print('Root Mean Squared Error (RMSE):', rmse)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a8f50adc",
+ "metadata": {},
+ "source": [
+ "### Save the model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "71e95e8b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Save the model to a file\n",
+ "model_filename = 'linear_regression_model.joblib'\n",
+ "joblib.dump(model, model_filename)\n",
+ "\n",
+ "print('Model saved to', model_filename)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "94594dfe",
+ "metadata": {},
+ "source": [
+ "### Tips to Improve Model Performance\n",
+ "\n",
+ "1. **Data Quality:**\n",
+ " - Ensure clean, high-quality data without missing values or outliers.\n",
+ "\n",
+ "2. **Feature Engineering:**\n",
+ " - Create relevant and new features that capture essential patterns in the data.\n",
+ "\n",
+ "3. **Model Selection:**\n",
+ " - Choose appropriate models and tune hyperparameters for better performance.\n",
+ "\n",
+ "4. **Ensemble Learning:**\n",
+ " - Combine multiple models to improve accuracy and robustness.\n",
+ "\n",
+ "5. **Regularization:**\n",
+ " - Implement regularization to prevent overfitting.\n",
+ "\n",
+ "7. **Domain Understanding:**\n",
+ " - Understand the problem domain to make informed model decisions.\n",
+ "\n",
+ "8. **Feedback Loop:**\n",
+ " - Continuously iterate and improve the model based on feedback and new data.\n",
+ "\n",
+ "---\n",
+ "\n",
+ "## HAPPY HACKING!!\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1052270e",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
From a35a3e9cb8d08a07fb727c36bc649bd186465c0f Mon Sep 17 00:00:00 2001
From: Margaret Awojide <49078266+awojidetola@users.noreply.github.com>
Date: Tue, 17 Oct 2023 10:52:45 +0100
Subject: [PATCH 3/8] add starter notebook
---
.../GPA_Prediction.ipynb | 42 +++++++++++++++----
1 file changed, 33 insertions(+), 9 deletions(-)
diff --git a/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb b/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
index 871ca736..c432aa68 100644
--- a/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
+++ b/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
@@ -35,10 +35,18 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"id": "6ee4356f",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Importation complete\n"
+ ]
+ }
+ ],
"source": [
"# Import necessary libraries\n",
"import pandas as pd\n",
@@ -49,8 +57,6 @@
"from sklearn.preprocessing import OrdinalEncoder, LabelEncoder\n",
"import warnings\n",
"import joblib\n",
- "# Set display options to show all columns\n",
- "pd.set_option('display.max_columns', None)\n",
"\n",
"# Ignore warnings\n",
"warnings.filterwarnings('ignore')\n",
@@ -59,15 +65,33 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 4,
"id": "ea57f719",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "ename": "EmptyDataError",
+ "evalue": "No columns to parse from file",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mEmptyDataError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32mc:\\Users\\USER\\Desktop\\HacktoberFest\\GPA_Prediction.ipynb Cell 3\u001b[0m line \u001b[0;36m2\n\u001b[0;32m 1\u001b[0m \u001b[39m# Load the GPA data from year1_gpa.csv\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m gpa_data \u001b[39m=\u001b[39m pd\u001b[39m.\u001b[39;49mread_csv(\u001b[39m\"\u001b[39;49m\u001b[39myear1_gpa.csv\u001b[39;49m\u001b[39m\"\u001b[39;49m)\n\u001b[0;32m 3\u001b[0m gpa_data\u001b[39m.\u001b[39mcolumns\n",
+ "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\readers.py:948\u001b[0m, in \u001b[0;36mread_csv\u001b[1;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)\u001b[0m\n\u001b[0;32m 935\u001b[0m kwds_defaults \u001b[39m=\u001b[39m _refine_defaults_read(\n\u001b[0;32m 936\u001b[0m dialect,\n\u001b[0;32m 937\u001b[0m delimiter,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 944\u001b[0m dtype_backend\u001b[39m=\u001b[39mdtype_backend,\n\u001b[0;32m 945\u001b[0m )\n\u001b[0;32m 946\u001b[0m kwds\u001b[39m.\u001b[39mupdate(kwds_defaults)\n\u001b[1;32m--> 948\u001b[0m \u001b[39mreturn\u001b[39;00m _read(filepath_or_buffer, kwds)\n",
+ "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\readers.py:611\u001b[0m, in \u001b[0;36m_read\u001b[1;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[0;32m 608\u001b[0m _validate_names(kwds\u001b[39m.\u001b[39mget(\u001b[39m\"\u001b[39m\u001b[39mnames\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39mNone\u001b[39;00m))\n\u001b[0;32m 610\u001b[0m \u001b[39m# Create the parser.\u001b[39;00m\n\u001b[1;32m--> 611\u001b[0m parser \u001b[39m=\u001b[39m TextFileReader(filepath_or_buffer, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[0;32m 613\u001b[0m \u001b[39mif\u001b[39;00m chunksize \u001b[39mor\u001b[39;00m iterator:\n\u001b[0;32m 614\u001b[0m \u001b[39mreturn\u001b[39;00m parser\n",
+ "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\readers.py:1448\u001b[0m, in \u001b[0;36mTextFileReader.__init__\u001b[1;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[0;32m 1445\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39moptions[\u001b[39m\"\u001b[39m\u001b[39mhas_index_names\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m kwds[\u001b[39m\"\u001b[39m\u001b[39mhas_index_names\u001b[39m\u001b[39m\"\u001b[39m]\n\u001b[0;32m 1447\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles: IOHandles \u001b[39m|\u001b[39m \u001b[39mNone\u001b[39;00m \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[1;32m-> 1448\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_engine \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_make_engine(f, \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mengine)\n",
+ "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\readers.py:1723\u001b[0m, in \u001b[0;36mTextFileReader._make_engine\u001b[1;34m(self, f, engine)\u001b[0m\n\u001b[0;32m 1720\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(msg)\n\u001b[0;32m 1722\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[1;32m-> 1723\u001b[0m \u001b[39mreturn\u001b[39;00m mapping[engine](f, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49m\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49moptions)\n\u001b[0;32m 1724\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mException\u001b[39;00m:\n\u001b[0;32m 1725\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n",
+ "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\c_parser_wrapper.py:93\u001b[0m, in \u001b[0;36mCParserWrapper.__init__\u001b[1;34m(self, src, **kwds)\u001b[0m\n\u001b[0;32m 90\u001b[0m \u001b[39mif\u001b[39;00m kwds[\u001b[39m\"\u001b[39m\u001b[39mdtype_backend\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m==\u001b[39m \u001b[39m\"\u001b[39m\u001b[39mpyarrow\u001b[39m\u001b[39m\"\u001b[39m:\n\u001b[0;32m 91\u001b[0m \u001b[39m# Fail here loudly instead of in cython after reading\u001b[39;00m\n\u001b[0;32m 92\u001b[0m import_optional_dependency(\u001b[39m\"\u001b[39m\u001b[39mpyarrow\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[1;32m---> 93\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_reader \u001b[39m=\u001b[39m parsers\u001b[39m.\u001b[39;49mTextReader(src, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[0;32m 95\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39munnamed_cols \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_reader\u001b[39m.\u001b[39munnamed_cols\n\u001b[0;32m 97\u001b[0m \u001b[39m# error: Cannot determine type of 'names'\u001b[39;00m\n",
+ "File \u001b[1;32mparsers.pyx:586\u001b[0m, in \u001b[0;36mpandas._libs.parsers.TextReader.__cinit__\u001b[1;34m()\u001b[0m\n",
+ "\u001b[1;31mEmptyDataError\u001b[0m: No columns to parse from file"
+ ]
+ }
+ ],
"source": [
"# Load the GPA data from year1_gpa.csv\n",
- "data_path = \"Data\\year1_gpa.csv\" # Adjust the path as needed\n",
+ "data_path = \"../Data/year1_gpa.csv\" # Adjust the path as needed\n",
"gpa_data = pd.read_csv(data_path,encoding='latin1')\n",
- "gpa_data.columns\n"
+ "gpa_data.columns"
]
},
{
@@ -348,7 +372,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.13"
+ "version": "3.11.3"
}
},
"nbformat": 4,
From 8d4a9ea994892931fe23a70dd0548143981ff3e6 Mon Sep 17 00:00:00 2001
From: Margaret Awojide <49078266+awojidetola@users.noreply.github.com>
Date: Wed, 18 Oct 2023 16:58:37 +0100
Subject: [PATCH 4/8] Add files via upload
---
.../GPA_Prediction.ipynb | 1268 ++++++++++++++++-
1 file changed, 1232 insertions(+), 36 deletions(-)
diff --git a/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb b/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
index c432aa68..2b91b380 100644
--- a/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
+++ b/Project_3/GPA_Prediction_awojidetola/GPA_Prediction.ipynb
@@ -35,7 +35,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 8,
"id": "6ee4356f",
"metadata": {},
"outputs": [
@@ -57,6 +57,7 @@
"from sklearn.preprocessing import OrdinalEncoder, LabelEncoder\n",
"import warnings\n",
"import joblib\n",
+ "import openpyxl\n",
"\n",
"# Ignore warnings\n",
"warnings.filterwarnings('ignore')\n",
@@ -65,32 +66,48 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 9,
"id": "ea57f719",
"metadata": {},
"outputs": [
{
- "ename": "EmptyDataError",
- "evalue": "No columns to parse from file",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mEmptyDataError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32mc:\\Users\\USER\\Desktop\\HacktoberFest\\GPA_Prediction.ipynb Cell 3\u001b[0m line \u001b[0;36m2\n\u001b[0;32m 1\u001b[0m \u001b[39m# Load the GPA data from year1_gpa.csv\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m gpa_data \u001b[39m=\u001b[39m pd\u001b[39m.\u001b[39;49mread_csv(\u001b[39m\"\u001b[39;49m\u001b[39myear1_gpa.csv\u001b[39;49m\u001b[39m\"\u001b[39;49m)\n\u001b[0;32m 3\u001b[0m gpa_data\u001b[39m.\u001b[39mcolumns\n",
- "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\readers.py:948\u001b[0m, in \u001b[0;36mread_csv\u001b[1;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)\u001b[0m\n\u001b[0;32m 935\u001b[0m kwds_defaults \u001b[39m=\u001b[39m _refine_defaults_read(\n\u001b[0;32m 936\u001b[0m dialect,\n\u001b[0;32m 937\u001b[0m delimiter,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 944\u001b[0m dtype_backend\u001b[39m=\u001b[39mdtype_backend,\n\u001b[0;32m 945\u001b[0m )\n\u001b[0;32m 946\u001b[0m kwds\u001b[39m.\u001b[39mupdate(kwds_defaults)\n\u001b[1;32m--> 948\u001b[0m \u001b[39mreturn\u001b[39;00m _read(filepath_or_buffer, kwds)\n",
- "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\readers.py:611\u001b[0m, in \u001b[0;36m_read\u001b[1;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[0;32m 608\u001b[0m _validate_names(kwds\u001b[39m.\u001b[39mget(\u001b[39m\"\u001b[39m\u001b[39mnames\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39mNone\u001b[39;00m))\n\u001b[0;32m 610\u001b[0m \u001b[39m# Create the parser.\u001b[39;00m\n\u001b[1;32m--> 611\u001b[0m parser \u001b[39m=\u001b[39m TextFileReader(filepath_or_buffer, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[0;32m 613\u001b[0m \u001b[39mif\u001b[39;00m chunksize \u001b[39mor\u001b[39;00m iterator:\n\u001b[0;32m 614\u001b[0m \u001b[39mreturn\u001b[39;00m parser\n",
- "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\readers.py:1448\u001b[0m, in \u001b[0;36mTextFileReader.__init__\u001b[1;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[0;32m 1445\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39moptions[\u001b[39m\"\u001b[39m\u001b[39mhas_index_names\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m kwds[\u001b[39m\"\u001b[39m\u001b[39mhas_index_names\u001b[39m\u001b[39m\"\u001b[39m]\n\u001b[0;32m 1447\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles: IOHandles \u001b[39m|\u001b[39m \u001b[39mNone\u001b[39;00m \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[1;32m-> 1448\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_engine \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_make_engine(f, \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mengine)\n",
- "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\readers.py:1723\u001b[0m, in \u001b[0;36mTextFileReader._make_engine\u001b[1;34m(self, f, engine)\u001b[0m\n\u001b[0;32m 1720\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(msg)\n\u001b[0;32m 1722\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[1;32m-> 1723\u001b[0m \u001b[39mreturn\u001b[39;00m mapping[engine](f, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49m\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49moptions)\n\u001b[0;32m 1724\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mException\u001b[39;00m:\n\u001b[0;32m 1725\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n",
- "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python311\\site-packages\\pandas\\io\\parsers\\c_parser_wrapper.py:93\u001b[0m, in \u001b[0;36mCParserWrapper.__init__\u001b[1;34m(self, src, **kwds)\u001b[0m\n\u001b[0;32m 90\u001b[0m \u001b[39mif\u001b[39;00m kwds[\u001b[39m\"\u001b[39m\u001b[39mdtype_backend\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m==\u001b[39m \u001b[39m\"\u001b[39m\u001b[39mpyarrow\u001b[39m\u001b[39m\"\u001b[39m:\n\u001b[0;32m 91\u001b[0m \u001b[39m# Fail here loudly instead of in cython after reading\u001b[39;00m\n\u001b[0;32m 92\u001b[0m import_optional_dependency(\u001b[39m\"\u001b[39m\u001b[39mpyarrow\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[1;32m---> 93\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_reader \u001b[39m=\u001b[39m parsers\u001b[39m.\u001b[39;49mTextReader(src, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[0;32m 95\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39munnamed_cols \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_reader\u001b[39m.\u001b[39munnamed_cols\n\u001b[0;32m 97\u001b[0m \u001b[39m# error: Cannot determine type of 'names'\u001b[39;00m\n",
- "File \u001b[1;32mparsers.pyx:586\u001b[0m, in \u001b[0;36mpandas._libs.parsers.TextReader.__cinit__\u001b[1;34m()\u001b[0m\n",
- "\u001b[1;31mEmptyDataError\u001b[0m: No columns to parse from file"
- ]
+ "data": {
+ "text/plain": [
+ "Index(['ID', 'Start time', 'Completion time', 'Email', 'Name',\n",
+ " 'Last modified time', 'Jamb score', 'English', 'Maths', 'Subject 3',\n",
+ " 'Subject 4', 'Subject 5', 'What was your age in Year One', 'Gender',\n",
+ " 'Do you have a disability?', 'Did you attend extra tutorials? ',\n",
+ " 'How would you rate your participation in extracurricular activities (tech, music, partying, fellowship, etc.) in Year One?',\n",
+ " 'How would you rate your class attendance in Year One',\n",
+ " 'How well did you participate in class activities (Assignments, Asking and Answering Questions, Writing Notes....)',\n",
+ " 'Rate your use of extra materials for study in Year One (Youtube, Other books, others).',\n",
+ " 'Morning', 'Afternoon', 'Evening', 'Late Night',\n",
+ " 'How many days per week did you do reading on average in Year One?',\n",
+ " 'On average, How many hours per day was used for personal study in Year One',\n",
+ " 'Did you teach your peers in Year One',\n",
+ " 'How many courses did you offer in Year One?',\n",
+ " 'Did you fall sick in Year One? if yes, How many times do you remember (0 if none)',\n",
+ " 'What was your study mode in Year 1',\n",
+ " 'Did you study the course your originally applied for?',\n",
+ " 'What was your monthly allowance in Year One?',\n",
+ " 'Rate the teaching style / method of the lectures received in Year One',\n",
+ " 'What type of higher institution did you attend in Year One\\n',\n",
+ " 'What was your CGPA in Year One?',\n",
+ " 'What grading system does your school use ( if others, type numbers only)'],\n",
+ " dtype='object')"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
"# Load the GPA data from year1_gpa.csv\n",
- "data_path = \"../Data/year1_gpa.csv\" # Adjust the path as needed\n",
- "gpa_data = pd.read_csv(data_path,encoding='latin1')\n",
+ "#data_path = \"../Data/year1_gpa.csv\" # Adjust the path as needed\n",
+ "#gpa_data = pd.read_csv(data_path,encoding='latin1')\n",
+ "#READ EXCEL FILE IN PANDAS\n",
+ "gpa_data = pd.read_excel('year1_gpa.xlsx')\n",
"gpa_data.columns"
]
},
@@ -105,10 +122,398 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 10,
"id": "319ebe42",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
id
\n",
+ "
start_time
\n",
+ "
completion_time
\n",
+ "
email
\n",
+ "
name
\n",
+ "
last_modified_time
\n",
+ "
jamb_score
\n",
+ "
english
\n",
+ "
maths
\n",
+ "
subject_3
\n",
+ "
...
\n",
+ "
taught_peers
\n",
+ "
courses_offered
\n",
+ "
times_fell_sick
\n",
+ "
study_mode
\n",
+ "
studied_original_course
\n",
+ "
What was your monthly allowance in Year One?
\n",
+ "
teaching_style_rating
\n",
+ "
institution_type
\n",
+ "
cgpa_year_one
\n",
+ "
grading_system
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
2
\n",
+ "
2023-09-30 09:42:21
\n",
+ "
2023-09-30 09:43:00
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
300
\n",
+ "
B
\n",
+ "
A
\n",
+ "
A
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
16 to 20
\n",
+ "
2
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
NaN
\n",
+ "
6
\n",
+ "
Public (Federal)
\n",
+ "
4.83
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
3
\n",
+ "
2023-09-30 10:06:49
\n",
+ "
2023-09-30 10:12:07
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
313
\n",
+ "
B
\n",
+ "
A
\n",
+ "
A
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
13 to 16
\n",
+ "
1
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
NaN
\n",
+ "
6
\n",
+ "
Public (Federal)
\n",
+ "
4.80
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
4
\n",
+ "
2023-10-02 07:00:32
\n",
+ "
2023-10-02 07:13:14
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
249
\n",
+ "
C
\n",
+ "
B
\n",
+ "
B
\n",
+ "
...
\n",
+ "
No, I studied alone
\n",
+ "
5 to 8
\n",
+ "
6
\n",
+ "
Full Time
\n",
+ "
No
\n",
+ "
NaN
\n",
+ "
2
\n",
+ "
Public (Federal)
\n",
+ "
3.1
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
5
\n",
+ "
2023-10-02 10:47:15
\n",
+ "
2023-10-02 10:52:56
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
213
\n",
+ "
C
\n",
+ "
B
\n",
+ "
B
\n",
+ "
...
\n",
+ "
No, I studied alone
\n",
+ "
16 to 20
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
No
\n",
+ "
NaN
\n",
+ "
1
\n",
+ "
Public (State)
\n",
+ "
3.33
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
6
\n",
+ "
2023-10-02 10:51:42
\n",
+ "
2023-10-02 10:53:39
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
345
\n",
+ "
C
\n",
+ "
A
\n",
+ "
A
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
0 to 4
\n",
+ "
2
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
NaN
\n",
+ "
5
\n",
+ "
Public (Federal)
\n",
+ "
4.6
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
126
\n",
+ "
128
\n",
+ "
2023-10-10 11:20:09
\n",
+ "
2023-10-10 11:24:17
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
295
\n",
+ "
A
\n",
+ "
C
\n",
+ "
B
\n",
+ "
...
\n",
+ "
No, I studied alone
\n",
+ "
9 to 12
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
No
\n",
+ "
11 to 20k
\n",
+ "
2
\n",
+ "
Public (Federal)
\n",
+ "
3.27
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
127
\n",
+ "
129
\n",
+ "
2023-10-10 15:46:05
\n",
+ "
2023-10-10 15:50:41
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
288
\n",
+ "
B
\n",
+ "
A
\n",
+ "
A
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
16 to 20
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
21 to 30k
\n",
+ "
2
\n",
+ "
Public (Federal)
\n",
+ "
4.81
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
128
\n",
+ "
130
\n",
+ "
2023-10-12 06:59:26
\n",
+ "
2023-10-12 07:02:08
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
316
\n",
+ "
C
\n",
+ "
A
\n",
+ "
B
\n",
+ "
...
\n",
+ "
No, I studied alone
\n",
+ "
5 to 8
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
11 to 20k
\n",
+ "
5
\n",
+ "
Public (Federal)
\n",
+ "
4.66
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
129
\n",
+ "
131
\n",
+ "
2023-10-14 12:05:32
\n",
+ "
2023-10-14 12:08:26
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
282
\n",
+ "
B
\n",
+ "
A
\n",
+ "
B
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
9 to 12
\n",
+ "
1
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
6 to 10k
\n",
+ "
7
\n",
+ "
Public (State)
\n",
+ "
4.77
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
130
\n",
+ "
132
\n",
+ "
2023-10-14 14:55:13
\n",
+ "
2023-10-14 15:19:46
\n",
+ "
anonymous
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
323
\n",
+ "
B
\n",
+ "
A
\n",
+ "
A
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
5 to 8
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
11 to 20k
\n",
+ "
4
\n",
+ "
Public (Federal)
\n",
+ "
4.56
\n",
+ "
5
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
131 rows × 36 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id start_time completion_time email name \\\n",
+ "0 2 2023-09-30 09:42:21 2023-09-30 09:43:00 anonymous NaN \n",
+ "1 3 2023-09-30 10:06:49 2023-09-30 10:12:07 anonymous NaN \n",
+ "2 4 2023-10-02 07:00:32 2023-10-02 07:13:14 anonymous NaN \n",
+ "3 5 2023-10-02 10:47:15 2023-10-02 10:52:56 anonymous NaN \n",
+ "4 6 2023-10-02 10:51:42 2023-10-02 10:53:39 anonymous NaN \n",
+ ".. ... ... ... ... ... \n",
+ "126 128 2023-10-10 11:20:09 2023-10-10 11:24:17 anonymous NaN \n",
+ "127 129 2023-10-10 15:46:05 2023-10-10 15:50:41 anonymous NaN \n",
+ "128 130 2023-10-12 06:59:26 2023-10-12 07:02:08 anonymous NaN \n",
+ "129 131 2023-10-14 12:05:32 2023-10-14 12:08:26 anonymous NaN \n",
+ "130 132 2023-10-14 14:55:13 2023-10-14 15:19:46 anonymous NaN \n",
+ "\n",
+ " last_modified_time jamb_score english maths subject_3 ... \\\n",
+ "0 NaN 300 B A A ... \n",
+ "1 NaN 313 B A A ... \n",
+ "2 NaN 249 C B B ... \n",
+ "3 NaN 213 C B B ... \n",
+ "4 NaN 345 C A A ... \n",
+ ".. ... ... ... ... ... ... \n",
+ "126 NaN 295 A C B ... \n",
+ "127 NaN 288 B A A ... \n",
+ "128 NaN 316 C A B ... \n",
+ "129 NaN 282 B A B ... \n",
+ "130 NaN 323 B A A ... \n",
+ "\n",
+ " taught_peers courses_offered times_fell_sick study_mode \\\n",
+ "0 Yes, but just a few times 16 to 20 2 Full Time \n",
+ "1 Yes, but just a few times 13 to 16 1 Full Time \n",
+ "2 No, I studied alone 5 to 8 6 Full Time \n",
+ "3 No, I studied alone 16 to 20 0 Full Time \n",
+ "4 Yes, but just a few times 0 to 4 2 Full Time \n",
+ ".. ... ... ... ... \n",
+ "126 No, I studied alone 9 to 12 0 Full Time \n",
+ "127 Yes, but just a few times 16 to 20 0 Full Time \n",
+ "128 No, I studied alone 5 to 8 0 Full Time \n",
+ "129 Yes, but just a few times 9 to 12 1 Full Time \n",
+ "130 Yes, but just a few times 5 to 8 0 Full Time \n",
+ "\n",
+ " studied_original_course What was your monthly allowance in Year One? \\\n",
+ "0 Yes NaN \n",
+ "1 Yes NaN \n",
+ "2 No NaN \n",
+ "3 No NaN \n",
+ "4 Yes NaN \n",
+ ".. ... ... \n",
+ "126 No 11 to 20k \n",
+ "127 Yes 21 to 30k \n",
+ "128 Yes 11 to 20k \n",
+ "129 Yes 6 to 10k \n",
+ "130 Yes 11 to 20k \n",
+ "\n",
+ " teaching_style_rating institution_type cgpa_year_one grading_system \n",
+ "0 6 Public (Federal) 4.83 5 \n",
+ "1 6 Public (Federal) 4.80 5 \n",
+ "2 2 Public (Federal) 3.1 5 \n",
+ "3 1 Public (State) 3.33 5 \n",
+ "4 5 Public (Federal) 4.6 5 \n",
+ ".. ... ... ... ... \n",
+ "126 2 Public (Federal) 3.27 5 \n",
+ "127 2 Public (Federal) 4.81 5 \n",
+ "128 5 Public (Federal) 4.66 5 \n",
+ "129 7 Public (State) 4.77 5 \n",
+ "130 4 Public (Federal) 4.56 5 \n",
+ "\n",
+ "[131 rows x 36 columns]"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"\n",
"\n",
@@ -161,10 +566,398 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 11,
"id": "9607b662",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
id
\n",
+ "
jamb_score
\n",
+ "
english
\n",
+ "
maths
\n",
+ "
subject_3
\n",
+ "
subject_4
\n",
+ "
subject_5
\n",
+ "
age_in_year_one
\n",
+ "
gender
\n",
+ "
has_disability
\n",
+ "
...
\n",
+ "
taught_peers
\n",
+ "
courses_offered
\n",
+ "
times_fell_sick
\n",
+ "
study_mode
\n",
+ "
studied_original_course
\n",
+ "
What was your monthly allowance in Year One?
\n",
+ "
teaching_style_rating
\n",
+ "
institution_type
\n",
+ "
cgpa_year_one
\n",
+ "
grading_system
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
2
\n",
+ "
300
\n",
+ "
B
\n",
+ "
A
\n",
+ "
A
\n",
+ "
B
\n",
+ "
B
\n",
+ "
16
\n",
+ "
Male
\n",
+ "
No
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
16 to 20
\n",
+ "
2
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
NaN
\n",
+ "
6
\n",
+ "
Public (Federal)
\n",
+ "
4.83
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
3
\n",
+ "
313
\n",
+ "
B
\n",
+ "
A
\n",
+ "
A
\n",
+ "
A
\n",
+ "
B
\n",
+ "
17
\n",
+ "
Male
\n",
+ "
No
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
13 to 16
\n",
+ "
1
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
NaN
\n",
+ "
6
\n",
+ "
Public (Federal)
\n",
+ "
4.80
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
4
\n",
+ "
249
\n",
+ "
C
\n",
+ "
B
\n",
+ "
B
\n",
+ "
B
\n",
+ "
C
\n",
+ "
22
\n",
+ "
Male
\n",
+ "
No
\n",
+ "
...
\n",
+ "
No, I studied alone
\n",
+ "
5 to 8
\n",
+ "
6
\n",
+ "
Full Time
\n",
+ "
No
\n",
+ "
NaN
\n",
+ "
2
\n",
+ "
Public (Federal)
\n",
+ "
3.1
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
5
\n",
+ "
213
\n",
+ "
C
\n",
+ "
B
\n",
+ "
B
\n",
+ "
C
\n",
+ "
B
\n",
+ "
17
\n",
+ "
Female
\n",
+ "
No
\n",
+ "
...
\n",
+ "
No, I studied alone
\n",
+ "
16 to 20
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
No
\n",
+ "
NaN
\n",
+ "
1
\n",
+ "
Public (State)
\n",
+ "
3.33
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
6
\n",
+ "
345
\n",
+ "
C
\n",
+ "
A
\n",
+ "
A
\n",
+ "
A
\n",
+ "
A
\n",
+ "
18
\n",
+ "
Male
\n",
+ "
No
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
0 to 4
\n",
+ "
2
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
NaN
\n",
+ "
5
\n",
+ "
Public (Federal)
\n",
+ "
4.6
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
126
\n",
+ "
128
\n",
+ "
295
\n",
+ "
A
\n",
+ "
C
\n",
+ "
B
\n",
+ "
B
\n",
+ "
C
\n",
+ "
17
\n",
+ "
Female
\n",
+ "
No
\n",
+ "
...
\n",
+ "
No, I studied alone
\n",
+ "
9 to 12
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
No
\n",
+ "
11 to 20k
\n",
+ "
2
\n",
+ "
Public (Federal)
\n",
+ "
3.27
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
127
\n",
+ "
129
\n",
+ "
288
\n",
+ "
B
\n",
+ "
A
\n",
+ "
A
\n",
+ "
A
\n",
+ "
A
\n",
+ "
18
\n",
+ "
Female
\n",
+ "
No
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
16 to 20
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
21 to 30k
\n",
+ "
2
\n",
+ "
Public (Federal)
\n",
+ "
4.81
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
128
\n",
+ "
130
\n",
+ "
316
\n",
+ "
C
\n",
+ "
A
\n",
+ "
B
\n",
+ "
B
\n",
+ "
B
\n",
+ "
16
\n",
+ "
Male
\n",
+ "
No
\n",
+ "
...
\n",
+ "
No, I studied alone
\n",
+ "
5 to 8
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
11 to 20k
\n",
+ "
5
\n",
+ "
Public (Federal)
\n",
+ "
4.66
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
129
\n",
+ "
131
\n",
+ "
282
\n",
+ "
B
\n",
+ "
A
\n",
+ "
B
\n",
+ "
B
\n",
+ "
A
\n",
+ "
18
\n",
+ "
Male
\n",
+ "
No
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
9 to 12
\n",
+ "
1
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
6 to 10k
\n",
+ "
7
\n",
+ "
Public (State)
\n",
+ "
4.77
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
130
\n",
+ "
132
\n",
+ "
323
\n",
+ "
B
\n",
+ "
A
\n",
+ "
A
\n",
+ "
A
\n",
+ "
B
\n",
+ "
16
\n",
+ "
Male
\n",
+ "
No
\n",
+ "
...
\n",
+ "
Yes, but just a few times
\n",
+ "
5 to 8
\n",
+ "
0
\n",
+ "
Full Time
\n",
+ "
Yes
\n",
+ "
11 to 20k
\n",
+ "
4
\n",
+ "
Public (Federal)
\n",
+ "
4.56
\n",
+ "
5
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
131 rows × 31 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id jamb_score english maths subject_3 subject_4 subject_5 \\\n",
+ "0 2 300 B A A B B \n",
+ "1 3 313 B A A A B \n",
+ "2 4 249 C B B B C \n",
+ "3 5 213 C B B C B \n",
+ "4 6 345 C A A A A \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "126 128 295 A C B B C \n",
+ "127 129 288 B A A A A \n",
+ "128 130 316 C A B B B \n",
+ "129 131 282 B A B B A \n",
+ "130 132 323 B A A A B \n",
+ "\n",
+ " age_in_year_one gender has_disability ... taught_peers \\\n",
+ "0 16 Male No ... Yes, but just a few times \n",
+ "1 17 Male No ... Yes, but just a few times \n",
+ "2 22 Male No ... No, I studied alone \n",
+ "3 17 Female No ... No, I studied alone \n",
+ "4 18 Male No ... Yes, but just a few times \n",
+ ".. ... ... ... ... ... \n",
+ "126 17 Female No ... No, I studied alone \n",
+ "127 18 Female No ... Yes, but just a few times \n",
+ "128 16 Male No ... No, I studied alone \n",
+ "129 18 Male No ... Yes, but just a few times \n",
+ "130 16 Male No ... Yes, but just a few times \n",
+ "\n",
+ " courses_offered times_fell_sick study_mode studied_original_course \\\n",
+ "0 16 to 20 2 Full Time Yes \n",
+ "1 13 to 16 1 Full Time Yes \n",
+ "2 5 to 8 6 Full Time No \n",
+ "3 16 to 20 0 Full Time No \n",
+ "4 0 to 4 2 Full Time Yes \n",
+ ".. ... ... ... ... \n",
+ "126 9 to 12 0 Full Time No \n",
+ "127 16 to 20 0 Full Time Yes \n",
+ "128 5 to 8 0 Full Time Yes \n",
+ "129 9 to 12 1 Full Time Yes \n",
+ "130 5 to 8 0 Full Time Yes \n",
+ "\n",
+ " What was your monthly allowance in Year One? teaching_style_rating \\\n",
+ "0 NaN 6 \n",
+ "1 NaN 6 \n",
+ "2 NaN 2 \n",
+ "3 NaN 1 \n",
+ "4 NaN 5 \n",
+ ".. ... ... \n",
+ "126 11 to 20k 2 \n",
+ "127 21 to 30k 2 \n",
+ "128 11 to 20k 5 \n",
+ "129 6 to 10k 7 \n",
+ "130 11 to 20k 4 \n",
+ "\n",
+ " institution_type cgpa_year_one grading_system \n",
+ "0 Public (Federal) 4.83 5 \n",
+ "1 Public (Federal) 4.80 5 \n",
+ "2 Public (Federal) 3.1 5 \n",
+ "3 Public (State) 3.33 5 \n",
+ "4 Public (Federal) 4.6 5 \n",
+ ".. ... ... ... \n",
+ "126 Public (Federal) 3.27 5 \n",
+ "127 Public (Federal) 4.81 5 \n",
+ "128 Public (Federal) 4.66 5 \n",
+ "129 Public (State) 4.77 5 \n",
+ "130 Public (Federal) 4.56 5 \n",
+ "\n",
+ "[131 rows x 31 columns]"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"# List of columns to drop\n",
"columns_to_drop = ['start_time', 'completion_time', 'email', 'name', 'last_modified_time']\n",
@@ -178,29 +971,432 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "74b3bddd",
+ "execution_count": 26,
+ "id": "4c7b7b4f",
"metadata": {},
"outputs": [],
"source": [
- "# Separate columns into numeric and categorical\n",
- "numeric_columns = gpa_data.select_dtypes(include=[np.number]).columns.tolist()\n",
- "categorical_columns = gpa_data.select_dtypes(include=[np.object]).columns.tolist()\n",
+ "#separte columns into numeric and categorical\n",
"\n",
- "# Print the lists\n",
- "print(\"Numeric Columns:\")\n",
- "print(numeric_columns)\n",
+ "numerical_cols = []\n",
+ "categorical_cols = []\n",
+ "for i in gpa_data.columns:\n",
+ " #print(i, gpa_data[i].dtype)\n",
+ " if gpa_data[i].dtype == 'object':\n",
+ " categorical_cols.append(i)\n",
+ " else:\n",
+ " numerical_cols.append(i)\n",
"\n",
- "print(\"\\nCategorical Columns:\")\n",
- "print(categorical_columns)\n"
+ "#cgpa_year_one should be numerical and it is the target variable"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 27,
"id": "82ff069e",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
""
],
"text/plain": [
- " id jamb_score english maths subject_3 subject_4 subject_5 \\\n",
- "0 2 300 B A A B B \n",
- "1 3 313 B A A A B \n",
- "2 4 249 C B B B C \n",
- "3 5 213 C B B C B \n",
- "4 6 345 C A A A A \n",
- ".. ... ... ... ... ... ... ... \n",
- "126 128 295 A C B B C \n",
- "127 129 288 B A A A A \n",
- "128 130 316 C A B B B \n",
- "129 131 282 B A B B A \n",
- "130 132 323 B A A A B \n",
+ " id jamb_score english maths subject_3 subject_4 subject_5 \\\n",
+ "0 2 300 B A A B B \n",
+ "1 3 313 B A A A B \n",
+ "2 4 249 C B B B C \n",
+ "3 5 213 C B B C B \n",
+ "4 6 345 C A A A A \n",
"\n",
- " age_in_year_one gender has_disability ... taught_peers \\\n",
- "0 16 Male No ... Yes, but just a few times \n",
- "1 17 Male No ... Yes, but just a few times \n",
- "2 22 Male No ... No, I studied alone \n",
- "3 17 Female No ... No, I studied alone \n",
- "4 18 Male No ... Yes, but just a few times \n",
- ".. ... ... ... ... ... \n",
- "126 17 Female No ... No, I studied alone \n",
- "127 18 Female No ... Yes, but just a few times \n",
- "128 16 Male No ... No, I studied alone \n",
- "129 18 Male No ... Yes, but just a few times \n",
- "130 16 Male No ... Yes, but just a few times \n",
+ " age_in_year_one gender has_disability ... taught_peers \\\n",
+ "0 16 Male No ... Yes, but just a few times \n",
+ "1 17 Male No ... Yes, but just a few times \n",
+ "2 22 Male No ... No, I studied alone \n",
+ "3 17 Female No ... No, I studied alone \n",
+ "4 18 Male No ... Yes, but just a few times \n",
"\n",
- " courses_offered times_fell_sick study_mode studied_original_course \\\n",
- "0 16 to 20 2 Full Time Yes \n",
- "1 13 to 16 1 Full Time Yes \n",
- "2 5 to 8 6 Full Time No \n",
- "3 16 to 20 0 Full Time No \n",
- "4 0 to 4 2 Full Time Yes \n",
- ".. ... ... ... ... \n",
- "126 9 to 12 0 Full Time No \n",
- "127 16 to 20 0 Full Time Yes \n",
- "128 5 to 8 0 Full Time Yes \n",
- "129 9 to 12 1 Full Time Yes \n",
- "130 5 to 8 0 Full Time Yes \n",
+ " courses_offered times_fell_sick study_mode studied_original_course \\\n",
+ "0 16 to 20 2 Full Time Yes \n",
+ "1 13 to 16 1 Full Time Yes \n",
+ "2 5 to 8 6 Full Time No \n",
+ "3 16 to 20 0 Full Time No \n",
+ "4 0 to 4 2 Full Time Yes \n",
"\n",
- " What was your monthly allowance in Year One? teaching_style_rating \\\n",
- "0 NaN 6 \n",
- "1 NaN 6 \n",
- "2 NaN 2 \n",
- "3 NaN 1 \n",
- "4 NaN 5 \n",
- ".. ... ... \n",
- "126 11 to 20k 2 \n",
- "127 21 to 30k 2 \n",
- "128 11 to 20k 5 \n",
- "129 6 to 10k 7 \n",
- "130 11 to 20k 4 \n",
+ " What was your monthly allowance in Year One? teaching_style_rating \\\n",
+ "0 NaN 6 \n",
+ "1 NaN 6 \n",
+ "2 NaN 2 \n",
+ "3 NaN 1 \n",
+ "4 NaN 5 \n",
"\n",
- " institution_type cgpa_year_one grading_system \n",
- "0 Public (Federal) 4.83 5 \n",
- "1 Public (Federal) 4.80 5 \n",
- "2 Public (Federal) 3.1 5 \n",
- "3 Public (State) 3.33 5 \n",
- "4 Public (Federal) 4.6 5 \n",
- ".. ... ... ... \n",
- "126 Public (Federal) 3.27 5 \n",
- "127 Public (Federal) 4.81 5 \n",
- "128 Public (Federal) 4.66 5 \n",
- "129 Public (State) 4.77 5 \n",
- "130 Public (Federal) 4.56 5 \n",
+ " institution_type cgpa_year_one grading_system \n",
+ "0 Public (Federal) 4.83 5 \n",
+ "1 Public (Federal) 4.80 5 \n",
+ "2 Public (Federal) 3.1 5 \n",
+ "3 Public (State) 3.33 5 \n",
+ "4 Public (Federal) 4.6 5 \n",
"\n",
- "[131 rows x 31 columns]"
+ "[5 rows x 31 columns]"
]
},
- "execution_count": 11,
+ "execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
@@ -966,12 +792,12 @@
"gpa_data.drop(columns=columns_to_drop, inplace=True)\n",
"\n",
"# Print the DataFrame after dropping columns\n",
- "gpa_data"
+ "gpa_data.head()"
]
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": 76,
"id": "4c7b7b4f",
"metadata": {},
"outputs": [],
@@ -985,14 +811,38 @@
" if gpa_data[i].dtype == 'object':\n",
" categorical_cols.append(i)\n",
" else:\n",
- " numerical_cols.append(i)\n",
- "\n",
- "#cgpa_year_one should be numerical and it is the target variable"
+ " numerical_cols.append(i)"
]
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 85,
+ "id": "b622ddd5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Cleaning and Transforming the Grading System and CGPA Year One Columns\n",
+ "gpa_data['grading_system'] = gpa_data['grading_system'].replace('A', np.nan)\n",
+ "gpa_data['cgpa_year_one'] = gpa_data['cgpa_year_one'].replace(\"no idea \", np.nan)\n",
+ "gpa_data['cgpa_year_one'] = gpa_data['cgpa_year_one'].replace(\"3.o\", np.nan)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 86,
+ "id": "2d3add7a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#convert grading system and cgpa year one to numeric\n",
+ "gpa_data['grading_system'] = pd.to_numeric(gpa_data['grading_system'])\n",
+ "gpa_data['cgpa_year_one'] = pd.to_numeric(gpa_data['cgpa_year_one'])\n",
+ "gpa_data['GPA_normal'] = gpa_data['cgpa_year_one'] / gpa_data['grading_system']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 88,
"id": "82ff069e",
"metadata": {},
"outputs": [
@@ -1028,8 +878,6 @@
"
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
LinearRegression()
"
- ],
"text/plain": [
- "LinearRegression()"
+ ""
]
},
- "execution_count": 92,
+ "execution_count": 254,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "X = gpa_data.drop(['id', 'GPA_normal'], axis=1) # Features excluding 'id' and 'GPA_normal'\n",
- "y = gpa_data['GPA_normal'] # Target variable\n",
- "\n",
- "# Train-test split\n",
- "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n",
- "\n",
- "# Initialize the Linear Regression model\n",
- "model = LinearRegression()\n",
- "\n",
- "# Train the model\n",
- "model.fit(X_train, y_train)"
+ "model.compile(optimizer='adam',loss='mse')\n",
+ "model.fit(x=X_train,y=y_train.values,\n",
+ " validation_data=(X_test,y_test.values),\n",
+ " batch_size=128,epochs=400)"
]
},
{
@@ -1327,7 +2767,7 @@
},
{
"cell_type": "code",
- "execution_count": 93,
+ "execution_count": 255,
"id": "9c958bb3",
"metadata": {},
"outputs": [
@@ -1335,7 +2775,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Root Mean Squared Error (RMSE): 0.030622339915251526\n"
+ "WARNING:tensorflow:6 out of the last 9 calls to .predict_function at 0x000002856D3070A0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.\n",
+ "1/1 [==============================] - 0s 261ms/step\n",
+ "Root Mean Squared Error (RMSE): 0.1828910029979454\n"
]
}
],
@@ -1348,6 +2790,33 @@
"print('Root Mean Squared Error (RMSE):', rmse)"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 260,
+ "id": "f1001b85",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ "