Yashar
Yashar

Reputation: 832

Adding geopandas boundary plot to plotly

I have two separate map plots, one is cultural boundaries in a country (just like the state borders) in the form of custom polygons based on latitude and longitude values, defined in geojson format. I can plot the polygons easily using geopandas:

states = gpd.read_file('myfile.geojson')
states.boundary.plot()

Here is a sample output:

enter image description here

The second is a series of latitudes and longitudes with corresponding values that I need to plot over a map layer, which I can do with plotly express's scatter_mapbox:

fig = px.scatter_mapbox(df_year,
                        lat='y', lon='x',
                        color='drought_index',
                        range_color=(-4, 4),
                        hover_data={'x': False, 'y': False},
                        zoom=5, height=800, width=1050,
                        center={'lat': 32.7089, 'lon': 53.6880},
                        color_continuous_scale=px.colors.diverging.RdYlGn,
                        color_continuous_midpoint=0,
                        )
fig.update_layout(mapbox_style="outdoors", mapbox_accesstoken=mb_token)

Which will look like this:

enter image description here

Is there any way to add these two plots together and have the scatter points and shape boundaries overlap on a single map? Meaning that on top of the mapbox layer, I have the scatter points and the boundaries of the polygons visible.

The problem is that geopandas plot uses matplotlib and returens AxesSubplot:, and I couldn't find any way to add this to the plotly fig. I tried the mpl_to_plotly() from plotly.tools, but it threw an exception on 'Canvas is null'.

I also tried to find a way to plot the geojson shapes with plotly, but all I could find was the choropleth mapbox which requires the shapes to be filled with a color. I tried to use it anyways by decreasing the opacity of the choropleth plot but it either will cover the scatter plot or be barely visible.

Any suggestion on how to approach this is appreciated.

Upvotes: 1

Views: 3794

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31236

  • you really described the solution. https://plotly.com/python/mapbox-layers/
  • have used UK county boundaries as cultural layer
  • have used UK hospitals to generate a scatter mapbox
  • "source": json.loads(gdf.geometry.to_json()), is really the solution to add a GEOJSON layer from a geopandas dataframe
import requests
import geopandas as gpd
import pandas as pd
import json, io
import plotly.express as px

# UK admin area boundaries
res = requests.get("https://opendata.arcgis.com/datasets/69dc11c7386943b4ad8893c45648b1e1_0.geojson")

# geopandas dataframe of "cultural layer"
gdf = gpd.GeoDataFrame.from_features(res.json()["features"], crs="CRS84")

# get some public addressess - hospitals.  data that can be scattered
dfhos = pd.read_csv(io.StringIO(requests.get("http://media.nhschoices.nhs.uk/data/foi/Hospital.csv").text),
    sep="¬",engine="python",)


fig = (
    px.scatter_mapbox(
        dfhos.head(100),
        lat="Latitude",
        lon="Longitude",
        color="Sector",
        hover_data=["OrganisationName", "Postcode"],
    )
    .update_traces(marker={"size": 10})
    .update_layout(
        mapbox={
            "style": "open-street-map",
            "zoom": 5,
            "layers": [
                {
                    "source": json.loads(gdf.geometry.to_json()),
                    "below": "traces",
                    "type": "line",
                    "color": "purple",
                    "line": {"width": 1.5},
                }
            ],
        },
        margin={"l": 0, "r": 0, "t": 0, "b": 0},
    )
)
fig.show()

enter image description here

Upvotes: 3

Related Questions