werner
werner

Reputation: 14845

Visualize a generic GeoJson file with Plotly

I want to plot some polygons contained in a GeoJson file. Is it possible to visualize a GeoJson file in Plotly that is not linked directly to a real world location?

As example I can use GeoPandas to plot a generic GeoJson file:

import json
geodata = json.loads(
"""{ "type": "FeatureCollection",
    "features": [
      { "type": "Feature",
        "geometry": {"type": "Polygon", "coordinates": [[[0,0],[0,1],[1,1]]]},
        "properties": {"id": "upper_left"}
      },
      { "type": "Feature",
        "geometry": {"type": "Polygon", "coordinates": [[[0,0],[1,1],[1,0]]]},
        "properties": {"id": "lower_right"}
      }
    ]
}""")

import geopandas as gpd
df_shapes = gpd.GeoDataFrame.from_features(geodata["features"])
df_shapes.plot(color="none")

The result displays the two polygons (triangles) contained in the GeoJson:

two polygons

How would I plot the same map using Plotly? This answer suggests to use scope to limit the base map that is shown. What can be done if there is no base map?

(I am not asking how to plot a square with a line. The GeoJson is just a simplified example.)

Upvotes: 0

Views: 751

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31166

plotly shapes can be drawn.

using traces

It's then a case of list / dict comprehensions to restructure geojson polygons to plotly structure

import json

geodata = json.loads(
    """{ "type": "FeatureCollection",
    "features": [
      { "type": "Feature",
        "geometry": {"type": "Polygon", "coordinates": [[[0,0],[0,1],[1,1]]]},
        "properties": {"id": "upper_left"}
      },
      { "type": "Feature",
        "geometry": {"type": "Polygon", "coordinates": [[[0,0],[1,1],[1,0]]]},
        "properties": {"id": "lower_right"}
      }
    ]
}"""
)

go.Figure(
    [
        go.Scatter(
            **{
                "x": [p[0] for p in f["geometry"]["coordinates"][0]],
                "y": [p[1] for p in f["geometry"]["coordinates"][0]],
                "fill": "toself",
                "name": f["properties"]["id"],
            }
        )
        for f in geodata["features"]
    ]
).update_layout(height=200, width=200, showlegend=False, margin={"l":0,"r":0,"t":0,"b":0})

enter image description here

using shapes

  • use geopandas geometry to get SVG then extract path
  • add theses polygons as shapes onto layout
from bs4 import BeautifulSoup

# input to plotly is path.  use shapely geometry svg path for this
df_shapes = df_shapes.assign(
    svgpath=df_shapes["geometry"].apply(
        lambda p: BeautifulSoup(p.svg()).find("path")["d"]
    )
)

go.Figure(
    layout=dict(
        height=200,
        width=200,
        showlegend=False,
        margin={"l": 0, "r": 0, "t": 0, "b": 0},
        xaxis={"range": [0, 1]},
        yaxis={"range": [0, 1]},
        shapes=[{"type": "path", "path": p} for p in df_shapes["svgpath"]],
    )
)

Upvotes: 1

Related Questions