How to Convert Coordinate Data to a GeoDataFrame in GeoPandas

How to Convert Coordinate Data to a GeoDataFrame in GeoPandas

Geographic data often comes in the form of latitude and longitude coordinates, which can be challenging to analyze or visualize effectively. GeoPandas provides tools to transform this raw coordinate data into rich geospatial formats. This tutorial will guide you through the process of converting coordinate data into a GeoDataFrame, a versatile data structure for geospatial analysis.

To demonstrate these concepts, we’ll work with a real-world dataset of abandoned vehicle reports in Chicago, Illinois. This dataset, sourced from the City of Chicago Data Portal, contains records of all open abandoned vehicle service complaints made to 311 between 2011 and mid-2016. By the end of this tutorial, you’ll have the skills to transform similar coordinate-based datasets into powerful geospatial resources.

Understanding the Dataset

Let’s start by examining the metadata of our dataset:

import geodatasets

# Get detailed information about the dataset
dataset_info = geodatasets.data.query_name('geoda.cars')

# Print the information
print("Dataset Information:")
for key, value in dataset_info.items():
    print(f"{key}: {value}")

This code will output detailed information about the dataset, including its source, description, and structure.

Key points from this metadata:

  • The dataset contains 137,867 rows and 21 columns.
  • It represents abandoned vehicles in Chicago from 2011 (311 complaints).
  • The geometry type is listed as “Point”, but as we’ll see, we’ll need to create this geometry ourselves.
  • The data is made available via a csv file. 

Loading the Dataset

Now, let’s load the dataset and check its type:

import pandas as pd
import geopandas as gpd
import geodatasets

# Load the dataset
path = geodatasets.get_path('geoda.cars')
cars_df = gpd.read_file(path)

print(type(cars_df))

Output: 

<class 'pandas.core.frame.DataFrame'>

Interestingly, even though we used gpd.read_file(), our data is loaded as a pandas DataFrame, not a GeoDataFrame. When you load a dataset with GeoPandas from a CSV file that contains latitude and longitude data, GeoPandas will not automatically create a geometry column for you. The data is initially loaded as a regular Pandas DataFrame, and you will need to explicitly create a geometry column from the coordinate information.

Converting to GeoDataFrame

In order to convert our DataFrame into a GeoDataFrame, we first need to create a geometry column from the latitude and longitude data. This is where Shapely comes into play. Shapely is a Python library used for manipulating and analyzing planar geometric objects, such as points, lines, and polygons. In our case, we will use the Point class from Shapely to represent each geographic location as a point geometry.

The Point class is a fundamental geometry type in Shapely, designed to represent a single point in a 2D space, defined by x (longitude) and y (latitude) coordinates. By combining this functionality with the GeoPandas library, we can efficiently convert tabular data (latitude/longitude) into spatial data by creating these point objects.

from shapely.geometry import Point

# Function to create Point, returning None for invalid coordinates
def create_point(lon, lat):
    try:
        return Point(float(lon), float(lat))
    except ValueError:
        return None

# Create Point geometry from latitude and longitude
cars_df['geometry'] = cars_df.apply(lambda row: create_point(row['Longitude'], row['Latitude']), axis=1)

# Create GeoDataFrame, dropping rows with invalid geometry
cars_gdf = gpd.GeoDataFrame(cars_df.dropna(subset=['geometry']), geometry='geometry', crs="EPSG:4326")

print(type(cars_gdf))

 Output: 

<class 'geopandas.geodataframe.GeoDataFrame'>

This code creates Point objects from the longitude and latitude data, handles potential errors, and then converts the DataFrame to a GeoDataFrame. We use EPSG:4326 (WGS84) as our Coordinate Reference System (CRS) because it’s a common standard for geographic coordinates.

Visualizing the Data

Now that we have a proper GeoDataFrame, we can create more insightful geospatial visualizations. Let’s create two side-by-side plots to better understand the distribution of abandoned vehicle reports:

import matplotlib.pyplot as plt
import seaborn as sns

# Set up the figure with two subplots
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(24, 12))

# Scatter plot
cars_gdf.plot(ax=ax1, markersize=1, alpha=0.5, color='blue')
ax1.set_title('Abandoned Vehicles in Chicago', fontsize=24, pad=10)
ax1.set_xlabel('Longitude', fontsize=18)
ax1.set_ylabel('Latitude', fontsize=18)

# Extract x and y coordinates from the geometry column
cars_gdf['x'] = cars_gdf.geometry.x
cars_gdf['y'] = cars_gdf.geometry.y

# Heatmap
sns.kdeplot(data=cars_gdf, x='x', y='y', cmap='YlOrRd', fill=True, cbar=True, ax=ax2)
ax2.set_title('Density of Abandoned Vehicles in Chicago', fontsize=24, pad=10)
ax2.set_xlabel('Longitude', fontsize=18)
ax2.set_ylabel('Latitude', fontsize=18)

# Add padding to the limits
padding = 0.05  # 5% padding
xlim = (cars_gdf.x.min() - padding * (cars_gdf.x.max() - cars_gdf.x.min()),
        cars_gdf.x.max() + padding * (cars_gdf.x.max() - cars_gdf.x.min()))
ylim = (cars_gdf.y.min() - padding * (cars_gdf.y.max() - cars_gdf.y.min()),
        cars_gdf.y.max() + padding * (cars_gdf.y.max() - cars_gdf.y.min()))

# Set limits for both plots
ax1.set_xlim(xlim)
ax1.set_ylim(ylim)
ax2.set_xlim(xlim)
ax2.set_ylim(ylim)

# Increase tick label size
ax1.tick_params(axis='both', which='major', labelsize=14)
ax2.tick_params(axis='both', which='major', labelsize=14)

# Adjust layout and display
plt.tight_layout()
plt.show()

This code creates two visualizations side by side:

  1. A scatter plot of all abandoned vehicle reports
  2. A heatmap showing the density of these reports

The scatter plot on the left provides a direct visualization of each reported abandoned vehicle. Each blue dot represents a single report, giving us a clear picture of the raw data distribution across Chicago. This plot helps us see the overall spread of reports and identify any obvious patterns or clusters.

The heatmap on the right offers a different perspective by showing the density of abandoned vehicle reports. Areas with higher concentrations of reports are represented by warmer colors (red and orange), while areas with fewer reports are shown in cooler colors (yellow and white). This visualization helps us quickly identify hotspots where abandoned vehicles are most frequently reported.

By comparing these two visualizations, we can gain several insights:

  1. Spatial Distribution: The scatter plot reveals that abandoned vehicle reports are spread throughout Chicago, but with varying densities in different areas.
  2. Hotspots: The heatmap clearly shows several high-density areas, particularly in the central and northern parts of the city. These hotspots could indicate neighborhoods that might benefit from increased attention from city services.

Transforming coordinate data into a GeoDataFrame enhances our analytical capabilities. This conversion allows for powerful spatial visualizations. The resulting maps offer valuable insights into abandoned vehicle patterns across Chicago.

Conclusion

In this tutorial, we’ve explored the process of transforming coordinate data into a GeoDataFrame, opening up possibilities for spatial analysis and visualization. The key steps we covered include:

  1. Creating Point geometry from coordinates
  2. Specifying the correct Coordinate Reference System (CRS)
  3. Visualizing spatial data effectively

This process is often needed when working with many real-world datasets that provide geographic information as coordinates rather than as ready-to-use geometric objects.

Leave a Reply

Your email address will not be published. Required fields are marked *