By the end of this lesson, you will be able to plot geographic data points on a map using Python’s Folium library to visualize spatial patterns.
What it is
Geospatial visualization involves representing data that has a physical location on Earth. The mental model is simple: every data point has coordinates (latitude and longitude) that correspond to a specific spot on a map. Related terms include GIS (Geographic Information Systems), choropleth maps (maps shaded by values), and heatmaps (density-based visualizations). Unlike standard charts, these visuals preserve spatial relationships, allowing analysts to see clusters, gaps, and regional trends.Why it matters
- Pattern Recognition: Identifies geographic clusters or outliers that are invisible in tabular data.
- Contextual Insight: Links business metrics (like sales) to physical locations (like store proximity).
- Communication: Maps are intuitive for stakeholders who may not understand complex statistical plots.
- Operational Planning: Helps in optimizing delivery routes, site selection, or resource allocation based on geography.
Syntax or steps
The most common workflow uses thefolium library in Python. The basic pattern involves three steps:
1. Initialize a map object with a center coordinate and zoom level.
2. Add markers or layers using your DataFrame’s latitude and longitude columns.
3. Save the map as an HTML file for viewing in a browser.
Example
import folium
import pandas as pd
# Sample data: City, Latitude, Longitude, Population
data = {
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston'],
'Lat': [40.7128, 34.0522, 41.8781, 29.7604],
'Lon': [-74.0060, -118.2437, -87.6298, -95.3698],
'Pop': [8336817, 3979576, 2693976, 2320268]
}
df = pd.DataFrame(data)
# Create a base map centered on the US
m = folium.Map(location=[39.8283, -98.5795], zoom_start=4)
# Add circle markers for each city
for idx, row in df.iterrows():
folium.CircleMarker(
location=[row['Lat'], row['Lon']],
radius=row['Pop'] / 100000, # Scale size by population
color='blue',
fill=True,
fill_color='lightblue',
popup=f"{row['City']}: {row['Pop']}"
).add_to(m)
# Save the map
m.save('us_cities_map.html')
Explanation: First, we create a DataFrame with location data. We initialize folium.Map with a central coordinate (roughly the US center) and a zoom level. We then iterate through the DataFrame, adding a CircleMarker for each row. The radius is dynamically calculated based on population to visualize magnitude. Finally, m.save() generates an interactive HTML file.
Common mistakes
- Swapping Lat/Lon: Latitude is North-South (-90 to 90); Longitude is East-West (-180 to 180). Swapping them places points in the wrong hemisphere or ocean.
- Ignoring Projection Distortion: Standard web maps use Mercator projection, which distorts size near poles. Do not compare areas visually without adjusting for projection.
- Overplotting: Plotting thousands of points without transparency or clustering makes the map unreadable. Use heatmaps or cluster plugins for large datasets.
- Missing Coordinate System: Ensure all data uses WGS84 (standard GPS coordinates). Mixing local grid systems with lat/lon causes misalignment.
When to use it
Compare geospatial plotting with standard scatter plots.| Feature | Geospatial Map | Standard Scatter Plot |
|---|---|---|
| Data Type | Location + Attribute | Numerical X + Numerical Y |
| Best For | Regional trends, logistics, demographics | Correlations, distributions, non-spatial relationships |
| Interpretation | Requires geographic context | Direct numerical comparison |
Practice
Guided Exercise: Modify the example above to change the marker color from blue to red if the population is greater than 3 million, otherwise keep it blue. Hint: Use anif statement inside the loop to determine the color parameter value before creating the CircleMarker.
Challenge: Add a tooltip to each marker that displays only the city name, while keeping the popup for detailed info.
Hint: Look up the tooltip parameter in the folium.CircleMarker documentation.