Interactive visualizations II#
Combining cartographic and non-cartographic visualizations#
Maps effectively show us where things happen, like where fire incidents occur. Charts, like bar graphs, show us for example how things change over time, such as fire incidents increasing or decreasing. What if we bring these two together?
With Folium, a Python library that lets us create interactive maps, we can add a special feature: pop-ups. Imagine clicking on a part of the map and seeing a chart pop up that shows how many incidents happened there over the years.
Here’s our plan: 1. For each region on our map, we’ll create a bar chart showing incidents over time. 2. We’ll turn these charts into pictures. 3. Then, we’ll add these pictures to our map. When you click on a region, you’ll see its chart.
This way, our map doesn’t just tell us where things happen but also shows us how things change over time in each place, making our map more interactive and full of information.
[1]:
import geopandas as gpd
import pandas as pd
import folium
from folium import Popup
import matplotlib.pyplot as plt
import io
import base64
# Load geographic data
shapefile_path = 'data/maakunnat_2024_milj.shp'
gdf = gpd.read_file(shapefile_path)
gdf = gdf.to_crs("EPSG:4326")
# Load incident data
csv_file_path = 'data/aggregate_year.csv'
df_incidents = pd.read_csv(csv_file_path)
# Create interactive map
map = folium.Map(location=[64, 26], zoom_start=6) # Adjust location and zoom as needed
def plot_bar_chart(region):
"""
Generates a base64 encoded image for the bar chart of incidents in a region.
"""
# Filter the data for the specified region
data = df_incidents[df_incidents['NAMEFIN'] == region]
# Create a figure and axis for the bar chart
fig, ax = plt.subplots(figsize=(4, 2.6))
# Plot the bar chart with years on the x-axis and number of incidents on the y-axis
ax.bar(data['year'], data['incidents'], color='#add8e6')
# Set the title and labels for the chart
ax.set_title(f"Incidents in {region}", fontsize=14)
ax.set_xlabel("Year", fontsize=10)
ax.set_ylabel("Number of Incidents", fontsize=10)
# Adjust the layout to fit everything nicely within the figure
plt.tight_layout()
# Create an in-memory buffer to save the plot as a PNG image
img = io.BytesIO()
plt.savefig(img, format='png')
# Close the plot to free up memory
plt.close()
# Reset the buffer's position to the beginning
img.seek(0)
# Encode the image in base64
base64_img = base64.b64encode(img.getvalue()).decode()
# Return the HTML <img> tag with the base64 encoded image
return f'<img src="data:image/png;base64,{base64_img}">'
# Adding regions to the map with popups and a solid light yellow color fill
for _, row in gdf.iterrows():
region = row['NAMEFIN'] # Adjust field name as necessary
popup_content = plot_bar_chart(region)
popup = Popup(popup_content, max_width=400, max_height='200px')
style_function = lambda x: {'fillColor': '#ffffcc', 'color': 'black', 'weight': 1, 'fillOpacity': 0.7}
folium.GeoJson(
row['geometry'],
tooltip=row['NAMEFIN'],
style_function=style_function
).add_child(popup).add_to(map)
# Display the map
map
[1]:
Interactive Heatmap#
A heatmap is a powerful tool for visualizing the concentration of events across a geographic area. Unlike traditional maps that use symbols (such as dots) to represent single occurrences, heatmaps use color intensity to show where events cluster together. This makes it easy to spot which areas have higher or lower activity, such as fire incidents in our case.
Why an interactive Heatmap:h
Visual Clarity: Heatmaps make it easier to understand dense clusters of events, providing a clear picture of fire hotspots.
Immediate Insights: By quickly showing where the highest concentrations of fires are, decision-makers can prioritize resources and responses more effectively.
Interactive Exploration: Users can zoom in and out, exploring different areas of interest in detail.
Here’s what we’re doing with the next code cell:
Load Data: We start by loading our fire data again for a fresh start.
Set Up the Map: We initialize a base map using Folium, centering it around the average latitude and longitude of our fire data. This ensures the map is focused on the relevant area where the fires occurred.
Prepare Heatmap Data: We create a list of latitude and longitude pairs from our fire data. If we had a measure of each fire’s intensity, we could use that to weight the heatmap. However, without it, we’re simply visualizing the locations of the fires.
Add the Heatmap Layer: Using Folium’s
HeatMap
plugin, we add our list of locations to the map as a heatmap layer. Areas with more fires will appear “hotter,” meaning they’ll be colored more intensely.Save and Display: Optionally, we save the map as an HTML file for easy sharing and display it directly in our environment.
[2]:
import pandas as pd
import folium
from folium.plugins import HeatMap
# Load your data
data_path = 'data/fire_data_for_map.csv' # Make sure to update this path
fire_data = pd.read_csv(data_path)
# Initialize a base map
map = folium.Map(location=[fire_data['LATITUDE'].mean(), fire_data['LONGITUDE'].mean()], zoom_start=5)
# If we had an intensity measure (e.g., 'FIRE_INTENSITY'), we could use it here; otherwise, just use lat, lon
heat_data = [[row['LATITUDE'], row['LONGITUDE']] for index, row in fire_data.iterrows()]
# Add a heatmap layer
HeatMap(heat_data).add_to(map)
# Save the map to an HTML file (optional)
map.save('html/wildfire_heatmap.html')
# Display the map
map
[2]:
This heatmap approach offers a dynamic way to visualize and interpret patterns in fire occurrences, enhancing our understanding of fire risks and distribution across the region.