{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# **Environmental Justice Analysis of Oil & Gas Spills in Colorado**\n",
    "## Author: **David P. Adams**\n",
    "### Date: **February 6, 2025**\n",
    "\n",
    "---\n",
    "\n",
    "### **Overview**\n",
    "This notebook analyzes oil and gas spills in Colorado through an **environmental justice (EJ) lens**. The primary objectives include:\n",
    "- Differentiating between **historical spills** (discovered later) and **recent spills** (reported as they occur).\n",
    "- Evaluating **reporting delays** and their relationships to **socioeconomic factors**.\n",
    "- Identifying **operator performance** in spill reporting.\n",
    "- Mapping the **spatial distribution** of spills.\n",
    "- Examining the **volume of spills** and whether larger spills occur disproportionately in certain areas.\n",
    "\n",
    "### **Key Analyses**\n",
    "1. **Data Processing & Cleaning**\n",
    "   - Converts timestamps for **discovery and reporting**.\n",
    "   - Categorizes spills into **historical vs. recent**.\n",
    "   - Handles missing and extreme values in **socioeconomic and spill volume data**.\n",
    "\n",
    "2. **Reporting Delays & Environmental Justice**\n",
    "   - Conducts **OLS regressions** to determine how income, poverty, unemployment, and race impact reporting delays.\n",
    "   - Compares **historical vs. recent spills** to examine shifts in reporting patterns.\n",
    "\n",
    "3. **Operator Performance**\n",
    "   - Identifies companies with the **most spills** and **longest reporting delays**.\n",
    "   - Compares reporting behavior across operators.\n",
    "\n",
    "4. **Spill Volume & Threshold Analysis**\n",
    "   - Categorizes spills as **\"More than Five Barrels\" (Y/N)**.\n",
    "   - Examines whether large spills are more common in marginalized areas.\n",
    "\n",
    "5. **Geospatial Analysis**\n",
    "   - Maps the **spatial distribution** of spills.\n",
    "   - Visualizes spill locations by **Spill Type** (Historical vs. Recent).\n",
    "\n",
    "### **Next Steps**\n",
    "- Further refine **geospatial clustering** for spill locations.\n",
    "- Analyze **changes in spill reporting trends over time**.\n",
    "- Investigate **regulatory impacts** on reporting behavior.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/dadams/miniconda3/envs/spatial_env2/lib/python3.10/site-packages/pandas/io/sql.py:1725: SAWarning: Did not recognize type 'geometry' of column 'geometry'\n",
      "  self.meta.reflect(bind=self.con, only=[table_name], views=True)\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "from sqlalchemy import create_engine\n",
    "import geopandas as gpd\n",
    "from dotenv import load_dotenv\n",
    "load_dotenv()\n",
    "\n",
    "import os\n",
    "\n",
    "# Database connection details from zshrc environment variables\n",
    "#  use .env file for local development\n",
    "\n",
    "\n",
    "db_name = 'colorado_spills'\n",
    "user = os.getenv('DB_USER')\n",
    "password = os.getenv('DB_PASSWORD')\n",
    "host = os.getenv('DB_HOST')\n",
    "port = os.getenv('DB_PORT')\n",
    "\n",
    "\n",
    "# Create an engine to connect to the PostgreSQL database\n",
    "engine = create_engine(f'postgresql+psycopg2://{user}:{password}@{host}:{port}/{db_name}')\n",
    "\n",
    "# Read in the spills_with_demographics_geog as spills\n",
    "spills = pd.read_sql_table('spills_with_demographics_geog', engine)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# use longitude and latitude to create a GeoDataFrame from spills data\n",
    "spills['geometry'] = gpd.points_from_xy(spills['Longitude'], spills['Latitude'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create a GeoDataFrame from spills\n",
    "spills_gdf = gpd.GeoDataFrame(spills, crs='EPSG:4326') \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# Ensure date columns are in datetime format\n",
    "spills_gdf['Date of Discovery'] = pd.to_datetime(spills_gdf['Date of Discovery'])\n",
    "spills_gdf['Initial Report Date'] = pd.to_datetime(spills_gdf['Initial Report Date'])\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# Calculate Report Delay\n",
    "spills_gdf['Report Delay (Days)'] = (spills_gdf['Initial Report Date'] - spills_gdf['Date of Discovery']).dt.days\n",
    "spills_gdf['Report Delay (Days)'] = spills_gdf['Report Delay (Days)'].apply(lambda x: max(x, 0))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Separate Historical vs. Recent Spills\n",
    "historical_spills = spills_gdf[spills_gdf['Spill Type'] == 'Historical']\n",
    "recent_spills = spills_gdf[spills_gdf['Spill Type'] == 'Recent']\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              count       mean         std  min  25%  50%  75%     max\n",
      "Spill Type                                                            \n",
      "Historical   5828.0  20.987646  205.864644  0.0  0.0  1.0  2.0  9261.0\n",
      "Recent      11062.0   4.075484   46.649970  0.0  0.0  1.0  2.0  2232.0\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Compare Reporting Delay\n",
    "report_delay_summary = spills_gdf.groupby('Spill Type')['Report Delay (Days)'].describe()\n",
    "print(report_delay_summary)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 32400 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Compare Spill Trends Over Time\n",
    "spills_by_year = spills_gdf.groupby(['Report Year', 'Spill Type']).size().unstack()\n",
    "spills_by_year.plot(kind='bar', figsize=(12,6), title='Spills by Year and Type')\n",
    "plt.xlabel('Year')\n",
    "plt.ylabel('Number of Spills')\n",
    "plt.legend(title='Spill Type')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Spill Type                                  Historical     Recent  \\\n",
      "Operator                                                            \n",
      "NOBLE ENERGY INC                              2.506479   1.448166   \n",
      "KERR MCGEE OIL & GAS ONSHORE LP               6.273743  11.311961   \n",
      "PDC ENERGY INC                                3.349296   2.347458   \n",
      "CAERUS PICEANCE LLC                          10.082090   0.980371   \n",
      "BONANZA CREEK ENERGY OPERATING COMPANY LLC   65.785714   1.126065   \n",
      "KP KAUFFMAN COMPANY INC                      58.846154   8.448276   \n",
      "CHEVRON USA INC                             251.076923   2.180723   \n",
      "HIGHPOINT OPERATING CORPORATION               1.027778   0.922667   \n",
      "CRESTONE PEAK RESOURCES OPERATING LLC         1.662420   0.962025   \n",
      "LARAMIE ENERGY LLC                           23.833333   1.707386   \n",
      "\n",
      "Spill Type                                  Total Spills  \n",
      "Operator                                                  \n",
      "NOBLE ENERGY INC                                    2402  \n",
      "KERR MCGEE OIL & GAS ONSHORE LP                     2243  \n",
      "PDC ENERGY INC                                      1182  \n",
      "CAERUS PICEANCE LLC                                 1051  \n",
      "BONANZA CREEK ENERGY OPERATING COMPANY LLC           643  \n",
      "KP KAUFFMAN COMPANY INC                              468  \n",
      "CHEVRON USA INC                                      467  \n",
      "HIGHPOINT OPERATING CORPORATION                      411  \n",
      "CRESTONE PEAK RESOURCES OPERATING LLC                394  \n",
      "LARAMIE ENERGY LLC                                   376  \n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Operator Performance Analysis\n",
    "operator_analysis = spills_gdf.groupby(['Operator', 'Spill Type'])['Report Delay (Days)'].mean().unstack()\n",
    "operator_analysis['Total Spills'] = spills_gdf.groupby('Operator').size()\n",
    "operator_analysis = operator_analysis.sort_values(by='Total Spills', ascending=False)\n",
    "print(operator_analysis.head(10))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Historical Spills Regression Results\n",
      "                             OLS Regression Results                            \n",
      "===============================================================================\n",
      "Dep. Variable:     Report Delay (Days)   R-squared:                       0.021\n",
      "Model:                             OLS   Adj. R-squared:                  0.020\n",
      "Method:                  Least Squares   F-statistic:                     24.68\n",
      "Date:                 Thu, 06 Feb 2025   Prob (F-statistic):           1.11e-24\n",
      "Time:                         20:01:46   Log-Likelihood:                -39230.\n",
      "No. Observations:                 5824   AIC:                         7.847e+04\n",
      "Df Residuals:                     5818   BIC:                         7.851e+04\n",
      "Df Model:                            5                                         \n",
      "Covariance Type:             nonrobust                                         \n",
      "===========================================================================================\n",
      "                              coef    std err          t      P>|t|      [0.025      0.975]\n",
      "-------------------------------------------------------------------------------------------\n",
      "const                     634.0041     58.001     10.931      0.000     520.301     747.707\n",
      "median_household_income    -0.0009      0.000     -5.495      0.000      -0.001      -0.001\n",
      "percent_poverty            -0.8355      0.667     -1.253      0.210      -2.142       0.471\n",
      "unemployment_rate           3.3076      2.124      1.558      0.119      -0.856       7.471\n",
      "percent_white              -5.5481      0.521    -10.640      0.000      -6.570      -4.526\n",
      "percent_hispanic           -3.1579      0.336     -9.401      0.000      -3.816      -2.499\n",
      "==============================================================================\n",
      "Omnibus:                    13872.070   Durbin-Watson:                   1.957\n",
      "Prob(Omnibus):                  0.000   Jarque-Bera (JB):        166139094.839\n",
      "Skew:                          24.022   Prob(JB):                         0.00\n",
      "Kurtosis:                     829.033   Cond. No.                     1.93e+06\n",
      "==============================================================================\n",
      "\n",
      "Notes:\n",
      "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n",
      "[2] The condition number is large, 1.93e+06. This might indicate that there are\n",
      "strong multicollinearity or other numerical problems.\n",
      "Recent Spills Regression Results\n",
      "                             OLS Regression Results                            \n",
      "===============================================================================\n",
      "Dep. Variable:     Report Delay (Days)   R-squared:                       0.001\n",
      "Model:                             OLS   Adj. R-squared:                  0.000\n",
      "Method:                  Least Squares   F-statistic:                     1.664\n",
      "Date:                 Thu, 06 Feb 2025   Prob (F-statistic):              0.140\n",
      "Time:                         20:01:46   Log-Likelihood:                -58199.\n",
      "No. Observations:                11062   AIC:                         1.164e+05\n",
      "Df Residuals:                    11056   BIC:                         1.165e+05\n",
      "Df Model:                            5                                         \n",
      "Covariance Type:             nonrobust                                         \n",
      "===========================================================================================\n",
      "                              coef    std err          t      P>|t|      [0.025      0.975]\n",
      "-------------------------------------------------------------------------------------------\n",
      "const                      -8.6015      7.381     -1.165      0.244     -23.070       5.867\n",
      "median_household_income  6.594e-06   2.43e-05      0.271      0.786   -4.11e-05    5.42e-05\n",
      "percent_poverty            -0.0951      0.089     -1.065      0.287      -0.270       0.080\n",
      "unemployment_rate           0.0821      0.366      0.224      0.823      -0.635       0.799\n",
      "percent_white               0.1344      0.067      1.999      0.046       0.003       0.266\n",
      "percent_hispanic            0.0856      0.048      1.801      0.072      -0.008       0.179\n",
      "==============================================================================\n",
      "Omnibus:                    29448.654   Durbin-Watson:                   1.630\n",
      "Prob(Omnibus):                  0.000   Jarque-Bera (JB):        693666950.411\n",
      "Skew:                          32.053   Prob(JB):                         0.00\n",
      "Kurtosis:                    1228.097   Cond. No.                     1.32e+06\n",
      "==============================================================================\n",
      "\n",
      "Notes:\n",
      "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n",
      "[2] The condition number is large, 1.32e+06. This might indicate that there are\n",
      "strong multicollinearity or other numerical problems.\n"
     ]
    }
   ],
   "source": [
    "import statsmodels.api as sm\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "# Environmental Justice Regressions\n",
    "# Define independent variables for environmental justice analysis\n",
    "independent_vars = ['median_household_income', 'percent_poverty', 'unemployment_rate', 'percent_white', 'percent_hispanic']\n",
    "\n",
    "# Drop missing or infinite values from historical spills\n",
    "historical_spills_clean = historical_spills[independent_vars + ['Report Delay (Days)']].replace([np.inf, -np.inf], np.nan).dropna()\n",
    "X_hist = historical_spills_clean[independent_vars]\n",
    "X_hist = sm.add_constant(X_hist)\n",
    "y_hist = historical_spills_clean['Report Delay (Days)']\n",
    "hist_model = sm.OLS(y_hist, X_hist).fit()\n",
    "print(\"Historical Spills Regression Results\")\n",
    "print(hist_model.summary())\n",
    "\n",
    "# Drop missing or infinite values from recent spills\n",
    "recent_spills_clean = recent_spills[independent_vars + ['Report Delay (Days)']].replace([np.inf, -np.inf], np.nan).dropna()\n",
    "X_recent = recent_spills_clean[independent_vars]\n",
    "X_recent = sm.add_constant(X_recent)\n",
    "y_recent = recent_spills_clean['Report Delay (Days)']\n",
    "recent_model = sm.OLS(y_recent, X_recent).fit()\n",
    "print(\"Recent Spills Regression Results\")\n",
    "print(recent_model.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Notes on Regression Results: Historical vs. Recent Spills**\n",
    "\n",
    "### **Historical Spills Regression Results**\n",
    "- **R² = 0.021** → The model explains **2.1%** of the variance in reporting delay. \n",
    "- **Key Findings:**\n",
    "  - **Income is negatively correlated with reporting delay**:  \n",
    "    - **(-0.0009, p < 0.001)** → Lower **median household income** is associated with **longer reporting delays**.\n",
    "  - **Percent White has a strong negative effect**:  \n",
    "    - **(-5.55, p < 0.001)** → Spills in **whiter areas** are reported **faster**.\n",
    "  - **Percent Hispanic also has a strong negative effect**:  \n",
    "    - **(-3.16, p < 0.001)** → Spills in **Hispanic areas** have longer delays.\n",
    "  - **Percent Poverty and Unemployment Rate are not significant**:  \n",
    "    - Poverty: **(-0.83, p = 0.21)**  \n",
    "    - Unemployment: **(3.31, p = 0.12)**\n",
    "- **Implications:**  \n",
    "  - Spills discovered late (historical) tend to be in **lower-income and more Hispanic areas**.\n",
    "  - There may be **under-monitoring or regulatory neglect** in these communities.\n",
    "\n",
    "---\n",
    "\n",
    "### **Recent Spills Regression Results**\n",
    "- **R² = 0.001** → The model explains almost **none** of the variance in reporting delay.\n",
    "- **Key Findings:**\n",
    "  - **Most variables are NOT statistically significant**:  \n",
    "    - Income: **(6.59e-06, p = 0.79)**  \n",
    "    - Poverty: **(-0.095, p = 0.29)**  \n",
    "    - Unemployment: **(0.082, p = 0.82)**\n",
    "  - **Percent White has a weak positive effect**:  \n",
    "    - **(0.134, p = 0.046)** → In recent spills, whiter areas have **slightly longer delays**.\n",
    "  - **Percent Hispanic is borderline significant**:  \n",
    "    - **(0.086, p = 0.072)** → Suggests **slightly longer delays** in Hispanic areas, but not as strong as in historical spills.\n",
    "- **Implications:**  \n",
    "  - **Socioeconomic factors do not strongly influence recent spill reporting.**\n",
    "  - This suggests that **recent spills are reported more uniformly** across different demographic areas.\n",
    "  - **Improvements in real-time monitoring may have reduced disparities** in reporting speed.\n",
    "\n",
    "---\n",
    "\n",
    "### **Comparative Takeaways**\n",
    "| Variable                | Historical Spills (p-value) | Recent Spills (p-value) | Interpretation |\n",
    "|-------------------------|---------------------------|-------------------------|---------------|\n",
    "| **Median Income**       | -0.0009 (**p < 0.001**)   | 6.59e-06 (p = 0.79)    | Income disparities matter **only for historical spills**. |\n",
    "| **Percent Poverty**     | -0.835 (p = 0.21)         | -0.095 (p = 0.29)      | Poverty does not significantly impact reporting delay. |\n",
    "| **Unemployment Rate**   | 3.307 (p = 0.12)         | 0.082 (p = 0.82)      | No meaningful relationship with reporting delay. |\n",
    "| **Percent White**       | -5.548 (**p < 0.001**)    | 0.134 (*p = 0.046*)    | Whiter areas had **faster historical reporting**, but slightly **slower** recent reporting. |\n",
    "| **Percent Hispanic**    | -3.158 (**p < 0.001**)    | 0.086 (p = 0.072)      | Hispanic areas experienced **longer delays historically**, but recent disparities are weaker. |\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 60740 characters]",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import seaborn as sns\n",
    "# Check spatial distribution of spills\n",
    "plt.figure(figsize=(10,6))\n",
    "sns.histplot(historical_spills['median_household_income'], bins=30, kde=True, label='Historical', color='red', alpha=0.6)\n",
    "sns.histplot(recent_spills['median_household_income'], bins=30, kde=True, label='Recent', color='blue', alpha=0.6)\n",
    "plt.legend()\n",
    "plt.title('Income Distribution for Historical vs. Recent Spills')\n",
    "plt.xlabel('Median Household Income')\n",
    "plt.ylabel('Count')\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Spill Type                                  Historical  Recent  Total Spills\n",
      "Operator                                                                    \n",
      "NOBLE ENERGY INC                                1775.0   627.0        2402.0\n",
      "KERR MCGEE OIL & GAS ONSHORE LP                 1432.0   811.0        2243.0\n",
      "PDC ENERGY INC                                   710.0   472.0        1182.0\n",
      "CAERUS PICEANCE LLC                              134.0   917.0        1051.0\n",
      "BONANZA CREEK ENERGY OPERATING COMPANY LLC        56.0   587.0         643.0\n",
      "KP KAUFFMAN COMPANY INC                           91.0   377.0         468.0\n",
      "CHEVRON USA INC                                   52.0   415.0         467.0\n",
      "HIGHPOINT OPERATING CORPORATION                   36.0   375.0         411.0\n",
      "CRESTONE PEAK RESOURCES OPERATING LLC            157.0   237.0         394.0\n",
      "LARAMIE ENERGY LLC                                24.0   352.0         376.0\n"
     ]
    }
   ],
   "source": [
    "# Operator comparison of historical vs recent spills\n",
    "operator_spill_type = spills_gdf.groupby(['Operator', 'Spill Type']).size().unstack()\n",
    "operator_spill_type['Total Spills'] = operator_spill_type.sum(axis=1)\n",
    "print(operator_spill_type.sort_values(by='Total Spills', ascending=False).head(10))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "More than Five Barrels  False  True \n",
      "Spill Type                          \n",
      "Historical               5271    557\n",
      "Recent                   6731   4331\n"
     ]
    }
   ],
   "source": [
    "volume_comparison_by_type = spills_gdf.groupby(['Spill Type', 'More than Five Barrels']).size().unstack()\n",
    "print(volume_comparison_by_type)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 160580 characters]",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import geopandas as gpd\n",
    "\n",
    "# Ensure spills_gdf is already a GeoDataFrame with the necessary data\n",
    "# spills_gdf = gpd.GeoDataFrame(...)\n",
    "\n",
    "# Create a plot for the spatial distribution of spills\n",
    "fig, ax = plt.subplots(figsize=(10, 6))\n",
    "\n",
    "# Plot the GeoDataFrame with optimizations\n",
    "spills_gdf.plot(\n",
    "    ax=ax,\n",
    "    marker='o', \n",
    "    alpha=0.6,  # Adjust transparency for better visibility\n",
    "    column='Spill Type', \n",
    "    legend=True, \n",
    "    legend_kwds={'title': \"Spill Type\"},  # Correctly specify the legend title\n",
    "    cmap='viridis'  # Use a colormap for better visual distinction\n",
    ")\n",
    "\n",
    "# Set plot title and labels\n",
    "ax.set_title('Spatial Distribution of Historical vs. Recent Spills', fontsize=14)\n",
    "ax.set_xlabel('Longitude', fontsize=12)\n",
    "ax.set_ylabel('Latitude', fontsize=12)\n",
    "\n",
    "# Improve layout\n",
    "plt.tight_layout()\n",
    "\n",
    "# Display the plot\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install contextily"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 715772 characters]",
      "text/plain": [
       "<Figure size 1200x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import geopandas as gpd\n",
    "import contextily as ctx\n",
    "\n",
    "# Ensure spills_gdf is in the Web Mercator CRS for compatibility with basemaps\n",
    "spills_gdf = spills_gdf.to_crs(epsg=3857)\n",
    "\n",
    "# Create a plot for the spatial distribution and population density\n",
    "fig, ax = plt.subplots(figsize=(12, 8))\n",
    "\n",
    "# Plot with population density\n",
    "spills_gdf.plot(\n",
    "    ax=ax,\n",
    "    column='total_population',\n",
    "    cmap='OrRd',  # Use a color map suggestive of density/intensity\n",
    "    legend=True,\n",
    "    legend_kwds={'label': \"Population Density\"},\n",
    "    alpha=0.6,\n",
    "    markersize=5  # Adjust marker size for better distinction\n",
    ")\n",
    "\n",
    "# Add a basemap for Colorado using contextily\n",
    "ctx.add_basemap(ax, source=ctx.providers.OpenStreetMap.Mapnik)  # Use OpenStreetMap as the base\n",
    "\n",
    "# Set plot title and labels\n",
    "ax.set_title('Spatial Distribution of Spills with Population Density', fontsize=14)\n",
    "ax.set_xlabel('Longitude', fontsize=12)\n",
    "ax.set_ylabel('Latitude', fontsize=12)\n",
    "\n",
    "# Remove axis for a clean look\n",
    "ax.set_axis_off()\n",
    "\n",
    "# Adjust layout\n",
    "plt.tight_layout()\n",
    "\n",
    "# Show plot\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 1175172 characters]",
      "text/plain": [
       "<Figure size 1200x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 1187192 characters]",
      "text/plain": [
       "<Figure size 1200x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import geopandas as gpd\n",
    "import contextily as ctx\n",
    "\n",
    "# Ensure spills_gdf is already a GeoDataFrame and projected into Web Mercator for basemaps\n",
    "spills_gdf = spills_gdf.to_crs(epsg=3857)\n",
    "\n",
    "# Filter historical and recent spills\n",
    "historical_spills = spills_gdf[spills_gdf['Spill Type'] == 'Historical']\n",
    "recent_spills = spills_gdf[spills_gdf['Spill Type'] == 'Recent']\n",
    "\n",
    "# Create the first map: Historical Spills and Population Density\n",
    "fig, ax1 = plt.subplots(figsize=(12, 8))\n",
    "spills_gdf.plot(\n",
    "    ax=ax1,\n",
    "    column='total_population',\n",
    "    cmap='YlOrRd',\n",
    "    legend=True,\n",
    "    legend_kwds={'label': \"Population Density\", 'shrink': 0.6},\n",
    "    alpha=0.3\n",
    ")\n",
    "historical_spills.plot(\n",
    "    ax=ax1,\n",
    "    color='blue',\n",
    "    markersize=10,\n",
    "    marker='o',\n",
    "    label='Historical Spills'\n",
    ")\n",
    "ctx.add_basemap(ax1, source=ctx.providers.OpenStreetMap.Mapnik, zoom=10)\n",
    "ax1.set_title('Population Density with Historical Spills', fontsize=14)\n",
    "ax1.legend(loc='upper right')\n",
    "ax1.set_axis_off()\n",
    "plt.tight_layout()\n",
    "\n",
    "# Create the second map: Recent Spills and Population Density\n",
    "fig, ax2 = plt.subplots(figsize=(12, 8))\n",
    "spills_gdf.plot(\n",
    "    ax=ax2,\n",
    "    column='total_population',\n",
    "    cmap='YlOrRd',\n",
    "    legend=True,\n",
    "    legend_kwds={'label': \"Population Density\", 'shrink': 0.6},\n",
    "    alpha=0.3\n",
    ")\n",
    "recent_spills.plot(\n",
    "    ax=ax2,\n",
    "    color='red',\n",
    "    markersize=10,\n",
    "    marker='x',\n",
    "    label='Recent Spills'\n",
    ")\n",
    "ctx.add_basemap(ax2, source=ctx.providers.OpenStreetMap.Mapnik, zoom=10)\n",
    "ax2.set_title('Population Density with Recent Spills', fontsize=14)\n",
    "ax2.legend(loc='upper right')\n",
    "ax2.set_axis_off()\n",
    "plt.tight_layout()\n",
    "\n",
    "# Display both plots\n",
    "plt.show()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "spatial_env2",
   "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.10.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
