Creates interactive geographic maps, choropleths, and spatial visualizations with GeoViews and GeoPandas. For point/line/polygon data, analysis like buffers/proximity, and tile basemaps.
npx claudepluginhub uw-ssec/rse-plugins --plugin holoviz-visualizationThis skill uses the workspace's default tool permissions.
Master geographic and mapping visualizations with GeoViews and spatial data handling. This skill covers creating interactive maps, analyzing geographic data, and visualizing spatial relationships.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Master geographic and mapping visualizations with GeoViews and spatial data handling. This skill covers creating interactive maps, analyzing geographic data, and visualizing spatial relationships.
GeoViews extends HoloViews with geographic support:
import geoviews as gv
import geopandas as gpd
from geoviews import tile_providers as gvts
# Load geographic data
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
# Basic map visualization
world_map = gv.Polygons(world, vdims=['name', 'pop_est']).opts(
title='World Population',
height=600,
width=800,
tools=['hover']
)
# Add tile layer background
tiled = gvts.ESRI.apply.opts(
alpha=0.4,
xaxis=None,
yaxis=None
) * world_map
# Create point features
cities_data = {
'city': ['New York', 'Los Angeles', 'Chicago'],
'latitude': [40.7128, 34.0522, 41.8781],
'longitude': [-74.0060, -118.2437, -87.6298],
'population': [8337000, 3990456, 2693976]
}
cities_gdf = gpd.GeoDataFrame(
cities_data,
geometry=gpd.points_from_xy(cities_data['longitude'], cities_data['latitude']),
crs='EPSG:4326'
)
# Visualize points
points = gv.Points(cities_gdf, kdims=['longitude', 'latitude'], vdims=['city', 'population'])
points = points.opts(
size=gv.dim('population').norm(min=5, max=50),
color='red',
tools=['hover', 'box_select']
)
# With tile background
map_with_points = gvts.CartoDEM.apply.opts(alpha=0.5) * points
# Color regions by data value
choropleth = gv.Polygons(world, vdims=['name', 'pop_est']).opts(
cmap='viridis',
color=gv.dim('pop_est').norm(),
colorbar=True,
height=600,
width=900,
tools=['hover']
)
# Add interactivity
choropleth = choropleth.opts(
hover_fill_color='red',
hover_fill_alpha=0.5
)
from holoviews import streams
# Create selectable map
selectable_map = gv.Polygons(world).opts(
tools=['box_select', 'tap'],
selection_fill_color='red',
nonselection_fill_alpha=0.2
)
# Stream for selection
selection_stream = streams.Selection1D()
def get_selected_data(index):
if index:
return world.iloc[index[0]]
return None
# Get info about selected region
selected_info = hv.DynamicMap(
lambda index: hv.Text(0, 0, str(get_selected_data(index))),
streams=[selection_stream]
)
# Multiple layers
terrain = gvts.Stamen.Terrain.apply.opts(alpha=0.3)
points = gv.Points(cities_gdf, kdims=['longitude', 'latitude'])
lines = gv.Lines(routes_gdf, kdims=['longitude', 'latitude'])
# Compose layers
map_composition = terrain * lines * points
# Faceted geographic display
faceted_maps = gv.Polygons(world, vdims=['name', 'continent']).facet('continent')
# Hexbin aggregation for point data
hexbin = gv.HexTiles(cities_gdf).opts(
cmap='viridis',
colorbar=True,
height=600,
width=800
)
# With tile background
map_hexbin = gvts.CartoDEM.apply.opts(alpha=0.4) * hexbin
# Combine different geographic layers
points_gdf = gpd.GeoDataFrame(
cities_data,
geometry=gpd.points_from_xy(cities_data['longitude'], cities_data['latitude']),
crs='EPSG:4326'
)
regions_gdf = gpd.read_file('regions.geojson')
# Spatial join: which cities are in which regions
joined = gpd.sjoin(points_gdf, regions_gdf, how='left', predicate='within')
# Visualize result
joined_map = gv.Points(joined, kdims=['longitude', 'latitude']) * \
gv.Polygons(regions_gdf)
from shapely.geometry import Point
# Create buffer zones
buffered = cities_gdf.copy()
buffered['geometry'] = buffered.geometry.buffer(1.0) # 1 degree
# Visualize buffered regions
buffers = gv.Polygons(buffered).opts(fill_alpha=0.3)
points = gv.Points(cities_gdf)
proximity_map = gvts.CartoDEM.apply.opts(alpha=0.3) * buffers * points
# Calculate distances between cities
from shapely.geometry import LineString
routes = []
for i in range(len(cities_gdf) - 1):
start = cities_gdf.geometry.iloc[i]
end = cities_gdf.geometry.iloc[i + 1]
route = LineString([start, end])
distance = start.distance(end)
routes.append({'geometry': route, 'distance': distance})
routes_gdf = gpd.GeoDataFrame(routes, crs='EPSG:4326')
# Visualize routes
route_lines = gv.Lines(routes_gdf, vdims=['distance']).opts(
color=gv.dim('distance').norm(),
cmap='plasma'
)
# Available tile providers
from geoviews import tile_providers as gvts
# Different styles
openstreetmap = gvts.OpenStreetMap.Mapnik
satellite = gvts.ESRI.WorldImagery
terrain = gvts.Stamen.Terrain
toner = gvts.Stamen.Toner
# Use with visualization
map_with_osm = gvts.OpenStreetMap.Mapnik * gv.Points(cities_gdf)
# Custom styling
base_map = gvts.CartoDEM.apply.opts(
alpha=0.5,
xaxis=None,
yaxis=None
)
# Always specify and manage CRS
gdf = gpd.read_file('data.geojson')
print(gdf.crs)
# Reproject if necessary
gdf_projected = gdf.to_crs('EPSG:3857') # Web Mercator
# When creating GeoDataFrame
gdf = gpd.GeoDataFrame(
data,
geometry=gpd.points_from_xy(lon, lat),
crs='EPSG:4326' # WGS84
)
# Use rasterization for dense point clouds
from holoviews.operation.datashader import rasterize
points = gv.Points(large_gdf, kdims=['x', 'y'])
rasterized = rasterize(points)
# Use tile-based rendering for massive datasets
# Consider breaking into GeoJSON tiles
# Combine multiple interaction tools
map_viz = gv.Polygons(gdf).opts(
tools=['hover', 'box_select', 'tap'],
hover_fill_color='yellow',
hover_fill_alpha=0.2,
selection_fill_color='red'
)
# Add complementary visualizations
statistics = hv.Text(0, 0, '') # Update based on selection
map_and_stats = hv.Column(map_viz, statistics)
# Use perceptually uniform colormaps
from colorcet import cm
map_viz = gv.Polygons(gdf, vdims=['value']).opts(
color=gv.dim('value').norm(),
cmap=cm['viridis'],
colorbar=True,
clim=(vmin, vmax)
)
def create_map_dashboard(layers_dict):
base_map = gvts.CartoDEM.apply.opts(alpha=0.4)
layers = [gv.Polygons(layers_dict[name]) for name in layers_dict]
return base_map * hv.Overlay(layers)
from holoviews import DynamicMap, streams
filter_stream = streams.Stream.define('filter', year=2020)
def update_map(year):
filtered_gdf = world[world['year'] == year]
return gv.Polygons(filtered_gdf, vdims=['name', 'value'])
dmap = DynamicMap(update_map, streams=[filter_stream])
def create_clustered_map(points_gdf, zoom_levels=[1, 5, 10, 20]):
# Use hexbin for aggregation at different scales
aggregated = gv.HexTiles(points_gdf, aggregation='count')
return aggregated.opts(responsive=True)
.hvplot(geo=True)gdf.is_valid.all()gdf.geometry.simplify(tolerance)