Interactive Visualizations#

Up to this point, we have created several plots for vector data, raster data, and data frames. However, Python also supports interactive visualizations through powerful libraries such as: plotly, bokeh, altair, dash, ipywidgets among others. Interactive visualizations allow users to explore data dynamically, providing an intuitive way to identify patterns, trends, and outliers. Python offers several powerful libraries for creating such visualizations, enabling interactivity with features like zooming, panning, tooltips, and filtering.

Interactive Maps with Vector Data#

Ipywidgets

Creating interactive maps with combination of Geopandas and ipywidgets in Python is a great way to visualize geospatial data dynamically. Below is an example of how you can create interactive maps using plotly with vector data.

import geopandas as gpd
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display

# Load Kanchanpur GPKG
vector_data = gpd.read_file("data/vector/kanchanpur.gpkg")

# Reproject vector data to a projected CRS (e.g., UTM zone 45N for this area)
vector_data = vector_data.to_crs(epsg=32645)

# Add few more columns
# Population
vector_data['Population'] = [
    37900, 46565, 72813, 49223, 52221, 64436, 40823,
    97216, 36368, 277108, 51835, 38199, 46773, 44571,
    48838, 11581, 131, 19211, 56755, 58257, 37573
]

# Calculate the area of each district (in square meters)
vector_data['area_m2'] = vector_data.geometry.area

# Convert the area from square meters to square kilometers
vector_data['Area'] = vector_data['area_m2'] / 1e6

# Add a new column with density (population/area)
vector_data['Density'] = vector_data['Population'] / vector_data['Area']

# Column names
print(vector_data.columns)
Index(['NAME', 'geometry', 'Population', 'area_m2', 'Area', 'Density'], dtype='object')
# Widget: Dropdown to select visualization type
viz_type = widgets.Dropdown(
    options=["Population", "Area", 'Density'],
    value="Population",
    description="Visualize:",
)

# Widget: Slider for adjusting edge line width
line_width = widgets.IntSlider(
    value=1, min=1, max=5, step=1, description="Line Width:"
)

# Function to update the map
def update_map(viz_type, line_width):
    fig, ax = plt.subplots(figsize=(10, 8))
    vector_data.plot(
        column=viz_type,
        cmap="viridis",
        edgecolor="black",
        linewidth=line_width,
        legend=True,
        ax=ax,
    )
    ax.set_title(f"Kanchanpur District Map: {viz_type}", fontsize=16)
    plt.show()

# Link the widgets with the function
widgets.interactive(update_map, viz_type=viz_type, line_width=line_width)

Why Use Ipywidgets?

  • Interactive: Enables user-driven exploration with widgets like sliders, dropdowns, and text inputs.

  • Lightweight: Does not rely heavily on external JavaScript libraries.

  • Compatible: Integrates seamlessly into Jupyter Book, JupyterLab, and Jupyter Notebook.

  • Customizable: You can build your own tailored widgets for any workflow.

Interactive Maps with Raster Data#

Plotly can visualize raster data as heatmaps or images on a geographic projection.

import plotly.express as px
import rasterio
import numpy as np

# Path to your raster file
raster_path = "data/raster/landcover_2019.tif"

# Open the raster file
with rasterio.open(raster_path) as src:
    raster_data = src.read(1)  # Single-band raster
    bounds = src.bounds  # Get raster bounds

# Create a 2D heatmap
fig = px.imshow(
    raster_data,
    color_continuous_scale="Viridis",
    title="ESA Land Cover Data 2019",
    origin="upper",
)

fig.update_layout(
    xaxis_title="Longitude",
    yaxis_title="Latitude",
)

fig.show()

Why use Plotly

  • Advanced interactivity

  • Hover/click events

  • Supports large raster arrays

Interactive Maps with Combined Data#

Combining vector and raster data in a single interactive map can provide a more comprehensive visualization. You can display both types of data (e.g., vector boundaries or polygons on top of a raster base map) using libraries like Folium combined with Ipywidgets for interaction. Below is how you can achieve this with a raster layer (for example, a landcover map) and vector data (such as the Kanchanpur polygon) in a single interactive map.

import folium
import geopandas as gpd
from folium import raster_layers
from ipywidgets import widgets

# Load the vector data (Kanchanpur polygon as GeoDataFrame)
gdf = gpd.read_file("data/vector/kanchanpur.gpkg")

# Load the raster data
import rasterio
from rasterio.plot import show

# Open the raster data
raster_file = "data/raster/landcover_2019.tif"
raster = rasterio.open(raster_file)
# Get the bounds of the raster
bounds = raster.bounds

# Create a base map
m = folium.Map(location=[28.7755, 80.2656], zoom_start=8)

# Add the raster data to the map
raster_layer = raster_layers.ImageOverlay(
    image=raster.read(1),  # Get the first band
    bounds=[[bounds.bottom, bounds.left], [bounds.top, bounds.right]],  # Coordinates for the extent of the raster data
    colormap=lambda x: [x / 255, 0.5, 0],  # Example colormap
    opacity=0.6,
)
raster_layer.add_to(m)

# Add vector data (Kanchanpur polygon) to the map
folium.GeoJson(gdf).add_to(m)

# Create an interactive control (checkbox) to toggle the visibility of the raster layer
raster_control = widgets.Checkbox(value=True, description="Show Raster")
def toggle_raster(change):
    if change['new']:
        raster_layer.add_to(m)
    else:
        m.remove_child(raster_layer)

raster_control.observe(toggle_raster, names='value')

# Show the map
m
Make this Notebook Trusted to load map: File -> Trust Notebook
  • The Kanchanpur polygon is loaded using GeoPandas (gpd.read_file), and it’s added to the Folium map using folium.GeoJson.

  • The raster data is read using Rasterio and displayed on the map as an ImageOverlay object. The bounds attribute defines the geographic extent of the raster.

  • A custom colormap function (lambda x: [x / 255, 0.5, 0]) is applied to the raster layer to provide a red-green color scale (you can adjust this based on your needs).

  • An ipywidgets.Checkbox is used to control the visibility of the raster layer on the map.

  • The toggle_raster function handles showing or hiding the raster layer based on the checkbox status.

For this tutorial, this concludes the coverage of Interactive Visualizations in Python. If you would like to explore additional packages for interactive maps, examples, or need clarification on any of the steps covered, please visit the GitHub repository: Python_tutorial and feel free to open an issue.