{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":82253,"databundleVersionId":8965849,"sourceType":"competition"}],"dockerImageVersionId":30732,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-18T04:51:34.385505Z","iopub.execute_input":"2024-07-18T04:51:34.385873Z","iopub.status.idle":"2024-07-18T04:51:35.384957Z","shell.execute_reply.started":"2024-07-18T04:51:34.385844Z","shell.execute_reply":"2024-07-18T04:51:35.383977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data  = pd.read_csv(\"/kaggle/input/f1nalyze-datathon-ieeecsmuj/train.csv\",low_memory=False)\nval = pd.read_csv('/kaggle/input/f1nalyze-datathon-ieeecsmuj/validation.csv', low_memory=False)\ntest = pd.read_csv('/kaggle/input/f1nalyze-datathon-ieeecsmuj/test.csv',low_memory=False)\ndata.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:51:35.386912Z","iopub.execute_input":"2024-07-18T04:51:35.387454Z","iopub.status.idle":"2024-07-18T04:52:26.164961Z","shell.execute_reply.started":"2024-07-18T04:51:35.387400Z","shell.execute_reply":"2024-07-18T04:52:26.163963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"row1 = data.iloc[1]\nrow2 = data.iloc[2]\nunequal_cols = row1 != row2\nprint(\"Columns where values are unequal:\")\nprint(unequal_cols[unequal_cols].index.tolist())","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:52:26.166319Z","iopub.execute_input":"2024-07-18T04:52:26.166658Z","iopub.status.idle":"2024-07-18T04:52:26.173308Z","shell.execute_reply.started":"2024-07-18T04:52:26.166628Z","shell.execute_reply":"2024-07-18T04:52:26.172219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"supplementary_variables = ['number',  'url_x', 'driverRef', 'driver_num', 'driver_code', 'forename','surname',\n                          'url_y', 'constructorRef','nationality_y', 'company', 'result_driver_standing', \n                           'fp1_date', 'fp1_time', 'fp2_date', 'fp2_time', 'fp3_date', 'fp3_time','quali_date',\n                           'quali_time', 'sprint_date', 'sprint_time', 'url', 'position_x', 'time_x', 'time_y']\ndata.drop(columns=supplementary_variables, inplace=True)\nval.drop(columns=supplementary_variables, inplace=True)\ntest.drop(columns=supplementary_variables, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:52:26.176293Z","iopub.execute_input":"2024-07-18T04:52:26.176693Z","iopub.status.idle":"2024-07-18T04:52:26.852381Z","shell.execute_reply.started":"2024-07-18T04:52:26.176659Z","shell.execute_reply":"2024-07-18T04:52:26.851494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert the 'date' and 'dob' columns to datetime format in the datasets\nfor df in [data, val, test]:\n    df['date'] = pd.to_datetime(df['date'])\n    df['dob'] = pd.to_datetime(df['dob'])\n\n# Define the function to calculate age at race\ndef calculate_age_at_race(df):\n    age = df['date'].dt.year - df['dob'].dt.year\n    age -= (df['date'].dt.month < df['dob'].dt.month) | ((df['date'].dt.month == df['dob'].dt.month) & (df['date'].dt.day < df['dob'].dt.day))\n    return age\n\n# Apply the function to create a new column for age\ndata['age_at_race'] = calculate_age_at_race(data)\nval['age_at_race'] = calculate_age_at_race(val)\ntest['age_at_race'] = calculate_age_at_race(test)","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:52:26.853532Z","iopub.execute_input":"2024-07-18T04:52:26.853818Z","iopub.status.idle":"2024-07-18T04:52:28.421114Z","shell.execute_reply.started":"2024-07-18T04:52:26.853795Z","shell.execute_reply":"2024-07-18T04:52:28.420228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess(data):\n    dat = data.sort_values(by=['driverId', 'date'])\n    data['recent_performance'] = dat.groupby('driverId')['points'].rolling(window=5, min_periods=1).mean().reset_index(level=0, drop=True)\n    data.drop(['dob', 'date'], inplace = True, axis = 1)\n    data.replace('\\\\N', np.nan, inplace=True)\n    # Average points per race\n    driver_points = data.groupby('driverId')['points'].sum()\n    driver_races = data.groupby('driverId')['racerId'].count()\n    data['average_points_per_race'] = data['driverId'].map(driver_points / driver_races)\n    data['driver_experience'] = data['driverId'].map(driver_races)\n    # Constructor performance\n    constructor_points = data.groupby('constructorId')['points'].sum()\n    constructor_races = data.groupby('constructorId')['racerId'].count()\n    data['constructor_avg_points_per_race'] = data['constructorId'].map(constructor_points / constructor_races)\n    driver_grid_positions = data.groupby('driverId')['grid'].sum()\n    data['average_grid_position'] = data['driverId'].map(driver_grid_positions / driver_races)\n\n    # Fastest lap frequency\n    driver_fastest_laps = data[data['fastestLap'].notna()].groupby('driverId')['fastestLap'].count()\n    data['fastest_lap_frequency'] = data['driverId'].map(driver_fastest_laps / driver_races)\n    # Step 1: Calculate total points by driver and circuit\n    circuit_points = data.groupby(['driverId', 'circuitId'])['points'].sum().reset_index()\n\n    # Step 2: Calculate the number of races by driver and circuit\n    circuit_races = data.groupby(['driverId', 'circuitId'])['racerId'].count().reset_index()\n    # Step 3: Merge total points and race count dataframes\n    circuit_performance = pd.merge(circuit_points, circuit_races, on=['driverId', 'circuitId'])\n\n    # Step 4: Compute average points per circuit\n    circuit_performance['average_points_per_circuit'] = circuit_performance['points'] / circuit_performance['racerId']\n\n    # Step 5: Create a dictionary for easy lookup\n    avg_points_dict = circuit_performance.set_index(['driverId', 'circuitId'])['average_points_per_circuit'].to_dict()\n\n    # Step 6: Map the average points per circuit to the original dataframe\n    data['average_points_per_circuit'] = data.apply(lambda row: avg_points_dict.get((row['driverId'], row['circuitId']), 0), axis=1)\n    cols = ['max_speed', 'fastestLap', 'rank', 'timetaken_in_millisec']\n    for col in cols:\n        data[col] = pd.to_numeric(data[col], errors='coerce')\n    return data","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:52:28.422404Z","iopub.execute_input":"2024-07-18T04:52:28.422745Z","iopub.status.idle":"2024-07-18T04:52:28.434669Z","shell.execute_reply.started":"2024-07-18T04:52:28.422717Z","shell.execute_reply":"2024-07-18T04:52:28.433716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = preprocess(data)\nval = preprocess(val)\ntest = preprocess(test)\ndata.drop([ 'positionText_y'], inplace = True, axis = 1)\nval.drop([ 'positionText_y'], inplace = True, axis = 1)","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:52:28.435804Z","iopub.execute_input":"2024-07-18T04:52:28.436102Z","iopub.status.idle":"2024-07-18T04:53:23.421316Z","shell.execute_reply.started":"2024-07-18T04:52:28.436075Z","shell.execute_reply":"2024-07-18T04:53:23.420185Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to convert time string to milliseconds\ndef time_to_milliseconds(time_str):\n    if pd.isna(time_str):\n        return None\n    parts = time_str.split(':')\n    minutes = int(parts[0])\n    seconds, milliseconds = map(float, parts[1].split('.'))\n    total_milliseconds = (minutes * 60 * 1000 + seconds * 1000 + milliseconds)\n    return total_milliseconds\n\n# Apply the function to the fastestLapTime column\ndata['fastestLapTime'] = data['fastestLapTime'].apply(time_to_milliseconds)\nval['fastestLapTime'] = val['fastestLapTime'].apply(time_to_milliseconds)\ntest['fastestLapTime'] = test['fastestLapTime'].apply(time_to_milliseconds)\ndata.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:53:23.422730Z","iopub.execute_input":"2024-07-18T04:53:23.423034Z","iopub.status.idle":"2024-07-18T04:53:27.147910Z","shell.execute_reply.started":"2024-07-18T04:53:23.423008Z","shell.execute_reply":"2024-07-18T04:53:27.146846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"numeric_cols = ['grid' ,'positionOrder','points','laps','timetaken_in_millisec' ,'fastestLap' ,'rank' ,'fastestLapTime' ,'max_speed'\n,'year' ,'round'  ,'points_y' ,'wins', 'recent_performance', 'age_at_race', 'average_points_per_race' , 'driver_experience', \n                'constructor_avg_points_per_race', 'average_grid_position', 'fastest_lap_frequency', 'average_points_per_circuit', \n               ]","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:53:27.149240Z","iopub.execute_input":"2024-07-18T04:53:27.149674Z","iopub.status.idle":"2024-07-18T04:53:27.154913Z","shell.execute_reply.started":"2024-07-18T04:53:27.149637Z","shell.execute_reply":"2024-07-18T04:53:27.153852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def treat_outliers_iqr(column):\n    Q1 = column.quantile(0.25)\n    Q3 = column.quantile(0.75)\n    IQR = Q3 - Q1\n    lower_bound = Q1 - 1.5 * IQR\n    upper_bound = Q3 + 1.5 * IQR\n    \n    # Treat outliers by capping them at the lower and upper bounds\n    column = np.where(column < lower_bound, lower_bound, column)\n    column = np.where(column > upper_bound, upper_bound, column)\n    \n    return column\n\nfor col in numeric_cols:\n    data[col] = treat_outliers_iqr(data[col])\n    val[col] = treat_outliers_iqr(val[col])\n    test[col] = treat_outliers_iqr(test[col])","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:53:27.159050Z","iopub.execute_input":"2024-07-18T04:53:27.159541Z","iopub.status.idle":"2024-07-18T04:53:28.880302Z","shell.execute_reply.started":"2024-07-18T04:53:27.159504Z","shell.execute_reply":"2024-07-18T04:53:28.879242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.preprocessing import StandardScaler\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.compose import ColumnTransformer\n\nclass CustomScaler(StandardScaler):\n    def fit(self, X, y=None):\n        # Fit only on non-NaN values\n        return super().fit(X[~np.isnan(X).any(axis=1)], y)\n\n    def transform(self, X, y=None):\n        # Copy the input data\n        X_copy = X.copy()\n        # Create a mask of NaN values\n        mask = np.isnan(X)\n        # Transform only non-NaN values\n        X_copy[~mask] = super().transform(X[~mask])\n        return X_copy\n\npreprocessor = ColumnTransformer(\n    transformers=[\n        ('num', CustomScaler(), numeric_cols)\n    ],\n    remainder='passthrough'\n)\n\npreprocessor.fit(data[numeric_cols])\ndata[numeric_cols] = preprocessor.transform(data[numeric_cols])\nval[numeric_cols] = preprocessor.transform(val[numeric_cols])\ntest[numeric_cols] = preprocessor.transform(test[numeric_cols])\ndata","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:53:28.881996Z","iopub.execute_input":"2024-07-18T04:53:28.882285Z","iopub.status.idle":"2024-07-18T04:53:40.319837Z","shell.execute_reply.started":"2024-07-18T04:53:28.882260Z","shell.execute_reply":"2024-07-18T04:53:40.318773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert all object data types to category data types\nfor col in data.columns:\n    if data[col].dtype == 'object':\n        data[col] = data[col].astype('category')\n        val[col] = val[col].astype('category')\n        test[col] = test[col].astype('category')\n\n# Verify the changes\ndata.info()","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:53:40.321099Z","iopub.execute_input":"2024-07-18T04:53:40.321410Z","iopub.status.idle":"2024-07-18T04:53:41.453606Z","shell.execute_reply.started":"2024-07-18T04:53:40.321383Z","shell.execute_reply":"2024-07-18T04:53:41.452582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the target variable and features\nX = data.drop(columns=['position'])\ny = data['position']\nvalx = val.drop(columns=['position'])\nvaly = val['position']","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:53:41.454808Z","iopub.execute_input":"2024-07-18T04:53:41.455113Z","iopub.status.idle":"2024-07-18T04:53:41.854328Z","shell.execute_reply.started":"2024-07-18T04:53:41.455087Z","shell.execute_reply":"2024-07-18T04:53:41.853450Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import xgboost as xgb\nfrom sklearn.metrics import mean_squared_error\n\n# Create an XGBoost Regressor\nxgb_regressor = xgb.XGBRegressor(objective='reg:squarederror', n_estimators=100, learning_rate=0.1, max_depth=5, random_state=42, enable_categorical = True)\n\nxgb_regressor.fit(X, y)\n\n# Make predictions\ny_train_pred = xgb_regressor.predict(X)\ny_val_pred = xgb_regressor.predict(valx)\n\n# Round predictions to the nearest integer\ny_train_pred_rounded = np.round(y_train_pred).astype(int)\ny_val_pred_rounded = np.round(y_val_pred).astype(int)\n\n# Evaluate the model using RMSE on rounded predictions\nrmse_train = np.sqrt(mean_squared_error(y, y_train_pred_rounded))\nrmse_val = np.sqrt(mean_squared_error(valy, y_val_pred_rounded))\n\nprint(f\"Training RMSE (rounded): {rmse_train:.4f}\")\nprint(f\"Validation RMSE (rounded): {rmse_val:.4f}\")","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:53:41.855246Z","iopub.execute_input":"2024-07-18T04:53:41.855552Z","iopub.status.idle":"2024-07-18T04:54:14.121345Z","shell.execute_reply.started":"2024-07-18T04:53:41.855527Z","shell.execute_reply":"2024-07-18T04:54:14.120310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import lightgbm as lgb\nfrom sklearn.metrics import mean_squared_error\n\n# Create a LightGBM Regressor\nlgb_regressor = lgb.LGBMRegressor(objective='regression', num_leaves=31, learning_rate=0.15, n_estimators=120, random_state=42)\n\n# Train the model\nlgb_regressor.fit(X, y)\n\n# Make predictions\ny_train_pred = lgb_regressor.predict(X)\ny_val_pred = lgb_regressor.predict(valx)\n\n# Round predictions to the nearest integer\ny_train_pred_rounded = np.round(y_train_pred).astype(int)\ny_val_pred_rounded = np.round(y_val_pred).astype(int)\n\n# Evaluate the model using RMSE on rounded predictions\nrmse_train = np.sqrt(mean_squared_error(y, y_train_pred_rounded))\nrmse_val = np.sqrt(mean_squared_error(valy, y_val_pred_rounded))\n\nprint(f\"Training RMSE (rounded): {rmse_train:.4f}\")\nprint(f\"Validation RMSE (rounded): {rmse_val:.4f}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:54:14.122949Z","iopub.execute_input":"2024-07-18T04:54:14.123298Z","iopub.status.idle":"2024-07-18T04:55:15.533445Z","shell.execute_reply.started":"2024-07-18T04:54:14.123268Z","shell.execute_reply":"2024-07-18T04:55:15.532303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"wesr = pd.read_csv('/kaggle/input/f1nalyze-datathon-ieeecsmuj/test.csv')\nres = pd.DataFrame()","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:55:15.534912Z","iopub.execute_input":"2024-07-18T04:55:15.535570Z","iopub.status.idle":"2024-07-18T04:55:18.511084Z","shell.execute_reply.started":"2024-07-18T04:55:15.535530Z","shell.execute_reply":"2024-07-18T04:55:18.509932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds =lgb_regressor.predict(test)\npreds = np.round(preds).astype(int)\n\nres['position'] = preds\nres['result_driver_standing'] = wesr['result_driver_standing']\nres.to_csv('res.csv', index = False)","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:55:18.512640Z","iopub.execute_input":"2024-07-18T04:55:18.513056Z","iopub.status.idle":"2024-07-18T04:55:20.225349Z","shell.execute_reply.started":"2024-07-18T04:55:18.513018Z","shell.execute_reply":"2024-07-18T04:55:20.224486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import lightgbm as lgb\nfrom sklearn.model_selection import GridSearchCV\nfrom sklearn.metrics import mean_squared_error\nimport numpy as np\n\n# Define the parameter grid\nparam_grid = {\n    'n_estimators': [100, 200, 300],\n    'learning_rate': [0.01, 0.1, 0.2],\n    'max_depth': [3, 5, 7],\n    'num_leaves': [31, 63, 127],\n    #'subsample': [0.8, 1.0],\n    #'colsample_bytree': [0.8, 1.0],\n    #'reg_alpha': [0, 0.1, 0.5],\n    #'reg_lambda': [0, 0.1, 0.5]\n}\n\n# Create a LightGBM Regressor\nlgb_regressor = lgb.LGBMRegressor(objective='regression', random_state=42)\n\n# Set up GridSearchCV\ngrid_search = GridSearchCV(estimator=lgb_regressor, param_grid=param_grid, scoring='neg_root_mean_squared_error', cv=3, verbose=1, n_jobs=-1)\n\n# Fit GridSearchCV to the data\ngrid_search.fit(X, y)\n\n# Get the best estimator\nbest_lgb = grid_search.best_estimator_\n\n# Make predictions\ny_train_pred = best_lgb.predict(X)\ny_val_pred = best_lgb.predict(valx)\n\n# Evaluate the model using RMSE\nrmse_train = np.sqrt(mean_squared_error(y, y_train_pred))\nrmse_val = np.sqrt(mean_squared_error(valy, y_val_pred))\n\nprint(f\"Training RMSE: {rmse_train:.4f}\")\nprint(f\"Validation RMSE: {rmse_val:.4f}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-07-18T04:55:20.720445Z","iopub.status.idle":"2024-07-18T04:55:20.720884Z","shell.execute_reply.started":"2024-07-18T04:55:20.720697Z","shell.execute_reply":"2024-07-18T04:55:20.720714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}