Skip to main content

Geographic Mapping with Vizly

Vizly ships with a bundled world atlas and USA states map out of the box. Plot country-level data with vz.map() and city-level data with vz.geo().

World map

The simplest way to show global data. Just pass country names and values.

import pandas as pd
import vizly as vz

vz.set_theme("corporate")

df = pd.DataFrame({
'name': ['United States', 'Canada', 'Brazil', 'Germany', 'United Kingdom',
'France', 'India', 'Japan', 'Australia', 'South Africa'],
'value': [92, 54, 61, 48, 57, 44, 73, 66, 39, 28],
})
chart = vz.map(df, title='Global demand', theme='corporate')
chart.to_html()

Map with USA states

Pass map="usa" to plot US state-level data.

import pandas as pd
import vizly as vz

df = pd.DataFrame({
'name': ['California', 'Texas', 'New York', 'Florida', 'Illinois',
'Pennsylvania', 'Ohio', 'Georgia', 'North Carolina', 'Michigan'],
'value': [88, 74, 61, 55, 49, 42, 38, 36, 34, 31],
})
chart = vz.map(df, map="usa", title='US demand by state', theme='corporate')

City-level geo charts

Plot specific coordinates on a map with vz.geo(). You provide longitude and latitude.

import pandas as pd
import vizly as vz

df = pd.DataFrame({
'name': ['NYC', 'LA', 'Chicago', 'Houston', 'Miami',
'Seattle', 'Denver', 'Boston'],
'lng': [-74.0, -118.2, -87.6, -95.4, -80.2, -122.3, -104.9, -71.1],
'lat': [40.7, 34.0, 41.9, 29.8, 25.8, 47.6, 39.7, 42.4],
'value': [88, 74, 61, 55, 49, 67, 42, 58],
})
chart = vz.geo(df, names='name', lng='lng', lat='lat', values='value',
title='City demand', theme='corporate')

GeoJSON overlays with layer composition

v1.0.1 adds overlay_geojson for layering supplementary GeoJSON data on top of existing charts. Use GeoLayer or the shorthand layers= parameter on vz.map() and vz.geo().

import vizly as vz

# Base map
df = vz.from_records([
{'name': 'Germany', 'value': 88},
{'name': 'France', 'value': 74},
])
chart = vz.map(df, title='European demand')

# Overlay GeoJSON with a join key (name_field / id_field)
chart.overlay_geojson(
"path/to/regions.geojson",
name_field="NAME_1",
id_field="id",
selectable=True,
)
chart.render("dashboard.html")

Layer composition via GeoLayer

from vizly.core.geo import GeoLayer

layer = GeoLayer(
geojson="http://localhost:8000/geojson/europe",
name_field="NAME_0",
style={"color": "#ff6b6b", "opacity": 0.5},
)

# Reuse same layer config across multiple maps
chart1 = vz.map(df, layers=[layer], title='Demand overlay')
chart2 = vz.map(df2, layers=[layer], title='Supply overlay')

Loading external GeoJSON

# Load a remote GeoJSON file for custom regions
from vizly.integrations.geo import load_map_geojson, map_path

geojson = load_map_geojson("https://data.example.com/eurostat.geojson")
# Or use a local path
geojson = map_path("data/nuts2.geojson")

Custom map registrations

Vizly supports registering custom GeoJSON map packs for regions not bundled by default.

import vizly as vz

# Register a custom GeoJSON map
vz.register_map_pack("europe", "path/to/europe.geojson")

# Now use it
df = pd.DataFrame({
'name': ['Germany', 'France', 'UK', 'Italy', 'Spain'],
'value': [88, 74, 61, 55, 49],
})
chart = vz.map(df, map="europe", title='European demand')
chart.to_html()

List available maps

import vizly as vz

bundled = vz.list_bundled_maps() # ['world', 'usa']
optional = vz.list_opt_in_maps() # maps registered via register_map_pack

JSON / SPA note

When using to_option() or json_response for SPAs, map GeoJSON is not embedded in the output. The SPA client must call echarts.registerMap() separately. HTML embeds (to_html()) handle this automatically.

# Safe for SPAs (no map data needed):
chart.to_option() # returns only the ECharts option dict

# HTML embed handles map registration:
chart.to_html() # calls echarts.registerMap for you

Full geographic dashboard

Combine world map, city geo chart, and supporting metrics.

import pandas as pd
import vizly as vz

vz.set_theme("corporate")

df_world = pd.DataFrame({
'name': ['United States', 'Canada', 'Brazil', 'Germany', 'United Kingdom',
'France', 'India', 'Japan', 'Australia', 'South Africa'],
'value': [92, 54, 61, 48, 57, 44, 73, 66, 39, 28],
})
df_cities = pd.DataFrame({
'name': ['NYC', 'LA', 'Chicago', 'Houston', 'Miami',
'Seattle', 'Denver', 'Boston'],
'lng': [-74.0, -118.2, -87.6, -95.4, -80.2, -122.3, -104.9, -71.1],
'lat': [40.7, 34.0, 41.9, 29.8, 25.8, 47.6, 39.7, 42.4],
'value': [88, 74, 61, 55, 49, 67, 42, 58],
})
df_bar = pd.DataFrame({
'region': ['North America', 'Europe', 'Asia Pacific', 'Latin America', 'Africa'],
'revenue': [245, 168, 192, 85, 42],
})

chart = vz.page(charts=[
vz.map(df_world, title='Global demand'),
vz.geo(df_cities, names='name', lng='lng', lat='lat', values='value',
title='City-level demand'),
vz.bar(df_bar, x='region', y='revenue', title='Revenue by region'),
], title="Geographic Analytics Dashboard")
chart.to_html()

Map type comparison

Map typeWhen to useData format
vz.map(df)Country-level global dataname (country), value (numeric)
vz.map(df, map="usa")US state-level dataname (state name), value (numeric)
vz.map(df, map="...")Custom GeoJSON regionname (region name in GeoJSON), value
vz.geo(df)City/scatter points on a maplng, lat, values
chart.overlay_geojson(...)Layer external GeoJSON over map/geoGeoJSON URL or path, name_field, id_field

Data input accepts pd.DataFrame or dict types (list[dict], dict[list]) directly. No forced DataFrame conversion in v1.0.1.

Theme tip

Try the v1.0.1 editor-themed maps: theme='editor_monokai', theme='editor_tokyo_night', or theme='editor_solarized_dark' for a developer-friendly geographic visualization style.