Mapping and spatial data

Geo mark

The Geo mark allows to draw geographic features such as points, lines and polygons. These marks data are passed as GeoJSON.

This allows to create choropleth maps such as the following:

from pyobsplot import Obsplot, Plot
import geopandas as gpd
import pandas as pd

# Load US counties from TopoJson with geopandas
counties = gpd.read_file("data/us-counties-10m.json", layer="counties")
counties["id"] = pd.to_numeric(counties["id"])
# Merge unemployment values
unemployment = pd.read_csv("data/us-county-unemployment.csv")
counties = pd.merge(counties, unemployment.loc[:, ("id", "rate")], on="id", how="left")

# Convert geodataframe to GeoJson
counties = counties.to_json()

# Map
Plot.plot(
    {
        "marks": [Plot.geo(counties, {"fill": js("(d) => d.properties.rate")})],
        "projection": "albers-usa",
        "color": {
            "type": "quantile",
            "n": 8,
            "scheme": "blues",
            "label": "Unemployment (%)",
            "legend": True,
        },
    }
)
3.344.555.56.27.4Unemployment (%)

Of course other marks can be used in conjunction with geo marks. This example represents the density of Walmarts supermarkets and is taken from the Mapping notebook.

# Load US states from TopoJson with geopandas and convert to GeoJson
states = gpd.read_file("data/us-counties-10m.json", layer="states").to_json()
nation = gpd.read_file("data/us-counties-10m.json", layer="nation").to_json()

walmarts = pd.read_csv("data/walmarts.tsv", sep="\t")

Plot.plot(
    {
        "marks": [
            Plot.density(
                walmarts,
                {"x": "longitude", "y": "latitude", "bandwidth": 12, "fill": "density"},
            ),
            Plot.dot(
                walmarts,
                {"x": "longitude", "y": "latitude", "r": 1, "fill": "currentColor"},
            ),
            Plot.geo(states, {"strokeOpacity": 0.3}),
            Plot.geo(nation),
        ],
        "projection": "albers",
        "color": {"scheme": "blues"},
    }
)

Raster mark

The Raster mark creates an image from spatial data.

Plot allows to do different type of spatial interpolations, such as nearest, which draws voronoi cells around values:

import polars as pl

ca55 = pl.read_csv("data/ca55-south.csv")


def flare_map(interpolation):
    return Plot.plot(
        {
            "x": {"axis": None},
            "y": {"axis": None},
            "inset": 10,
            "marginBottom": 2,
            "height": 500,
            "color": {"type": "diverging"},
            "marks": [
                Plot.raster(
                    ca55,
                    {
                        "x": "LONGITUDE",
                        "y": "LATITUDE",
                        "fill": "MAG_IGRF90",
                        "interpolate": interpolation,
                    },
                ),
                Plot.frame(),
            ],
        }
    )


flare_map("nearest")

Or the more recent random walk interpolation:

flare_map("random-walk")