{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceType":"competition","sourceId":131571,"databundleVersionId":15777525}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-02-23T05:36:52.029401Z","iopub.execute_input":"2026-02-23T05:36:52.029611Z","iopub.status.idle":"2026-02-23T05:36:53.043858Z","shell.execute_reply.started":"2026-02-23T05:36:52.029589Z","shell.execute_reply":"2026-02-23T05:36:53.043082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport xgboost as xgb\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import mean_squared_error\nfrom sklearn.preprocessing import LabelEncoder\nimport warnings\nwarnings.filterwarnings('ignore')\n\nprint(\"Libraries loaded successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-23T05:37:54.832359Z","iopub.execute_input":"2026-02-23T05:37:54.832685Z","iopub.status.idle":"2026-02-23T05:37:55.795112Z","shell.execute_reply.started":"2026-02-23T05:37:54.832657Z","shell.execute_reply":"2026-02-23T05:37:55.794239Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define the base path\nbase_path = \"/kaggle/input/a-cloned-airbnb-booking-prediction-competition-k-353/\"\n\n# Load static info and target/test IDs\nprop_info = pd.read_csv(base_path + \"property_info.csv\")\ntrain_target = pd.read_csv(base_path + \"reserve_2016Q3_train.csv\")\ntest_ids = pd.read_csv(base_path + \"PropertyID_test.csv\")\n\n# Load daily time-series data\nq1 = pd.read_csv(base_path + \"listing_2016Q1.csv\")\nq2 = pd.read_csv(base_path + \"listing_2016Q2.csv\")\n\nprint(\"Data loaded successfully!\")\nprint(f\"Properties: {prop_info.shape[0]}, Train labels: {train_target.shape[0]}, Test IDs: {test_ids.shape[0]}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-23T05:38:03.842653Z","iopub.execute_input":"2026-02-23T05:38:03.843498Z","iopub.status.idle":"2026-02-23T05:38:09.635093Z","shell.execute_reply.started":"2026-02-23T05:38:03.843467Z","shell.execute_reply":"2026-02-23T05:38:09.634447Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Combine Q1 and Q2 data\nq1_q2_combined = pd.concat([q1, q2], ignore_index=True)\n\n# Use the exact column name from your output\nprice_col_name = 'Price'\n\n# Clean the price column in case it has string characters like '$' or ','\nif q1_q2_combined[price_col_name].dtype == 'object':\n    q1_q2_combined[price_col_name] = q1_q2_combined[price_col_name].replace(\n        {'\\$': '', ',': ''}, regex=True\n    ).astype(float)\n\n# Perform the aggregation\ndaily_agg = q1_q2_combined.groupby('PropertyID').agg(\n    avg_price=(price_col_name, 'mean'),\n    max_price=(price_col_name, 'max'),\n    days_listed=('PropertyID', 'count')\n).reset_index()\n\nprint(\"Time-series data aggregated successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-23T05:40:21.552673Z","iopub.execute_input":"2026-02-23T05:40:21.553304Z","iopub.status.idle":"2026-02-23T05:40:22.268927Z","shell.execute_reply.started":"2026-02-23T05:40:21.553276Z","shell.execute_reply":"2026-02-23T05:40:22.268251Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Columns in training target:\", train_target.columns.tolist())\n\n# Assuming prop_info uses 'id', rename it to 'PropertyID' to match the other dataframes\nif 'id' in prop_info.columns:\n    prop_info = prop_info.rename(columns={'id': 'PropertyID'})\n\n# Merge static property info with the aggregated daily features\nfull_features = prop_info.merge(daily_agg, on='PropertyID', how='left')\n\n# Convert text/categorical columns (like property type or country) into numbers\ncategorical_cols = full_features.select_dtypes(include=['object']).columns\nle = LabelEncoder()\nfor col in categorical_cols:\n    full_features[col] = le.fit_transform(full_features[col].astype(str))\n\n# Create final Train and Test datasets by bringing everything together\ntrain_df = train_target.merge(full_features, on='PropertyID', how='left')\ntest_df = test_ids.merge(full_features, on='PropertyID', how='left')\n\n# Automatically grab the target column (assuming it's the last column in reserve_2016Q3_train.csv)\ntarget_col = train_target.columns[-1] \nprint(f\"Using '{target_col}' as the target column.\")\n\n# Split into X (features) and y (target)\nX = train_df.drop(columns=['PropertyID', target_col])\ny = train_df[target_col]\nX_test = test_df.drop(columns=['PropertyID'])\n\nprint(\"Data merged and ready for training!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-23T05:40:32.172759Z","iopub.execute_input":"2026-02-23T05:40:32.173061Z","iopub.status.idle":"2026-02-23T05:40:32.439840Z","shell.execute_reply.started":"2026-02-23T05:40:32.173038Z","shell.execute_reply":"2026-02-23T05:40:32.439065Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Split data into train and validation sets to monitor performance\nX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)\n\n# Initialize the XGBRegressor \nxgb_model = xgb.XGBRegressor(\n    n_estimators=1000,\n    learning_rate=0.05,\n    max_depth=6,\n    objective='reg:squarederror',\n    eval_metric='rmse',\n    early_stopping_rounds=20,  # Placed here in the constructor\n    random_state=42\n)\n\n# Fit the model using the validation set to stop early if it stops improving\nxgb_model.fit(\n    X_train, y_train,\n    eval_set=[(X_val, y_val)],\n    verbose=50\n)\n\n# Calculate and print the validation Mean Squared Error (MSE)\nval_preds = xgb_model.predict(X_val)\nval_mse = mean_squared_error(y_val, val_preds)\nprint(f\"\\nValidation MSE: {val_mse:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-23T05:41:15.877956Z","iopub.execute_input":"2026-02-23T05:41:15.878256Z","iopub.status.idle":"2026-02-23T05:41:17.198001Z","shell.execute_reply.started":"2026-02-23T05:41:15.878233Z","shell.execute_reply":"2026-02-23T05:41:17.197450Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Predict on the test set\ntest_preds = xgb_model.predict(X_test)\n\n# Competition requires integer predictions (no decimals)\n# We use np.round and clip at 0 because a property cannot have negative bookings\ntest_preds_rounded = np.clip(np.round(test_preds), 0, None).astype(int)\n\n# Create submission dataframe with exact required column names\nsubmission = pd.DataFrame({\n    'PropertyID_test': test_df['PropertyID'],\n    'Pred': test_preds_rounded\n})\n\n# Save to CSV without the index\nsubmission.to_csv('submission.csv', index=False)\nprint(\"submission.csv successfully created! 🚀\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-23T05:41:25.547875Z","iopub.execute_input":"2026-02-23T05:41:25.548429Z","iopub.status.idle":"2026-02-23T05:41:25.654741Z","shell.execute_reply.started":"2026-02-23T05:41:25.548403Z","shell.execute_reply":"2026-02-23T05:41:25.654009Z"}},"outputs":[],"execution_count":null}]}