Is there a way to create additional choropleth (ideally Mapbox choropleths, but I'd settle for Plotly's standard choropleth function) maps and layer them on top of a base choropleth so that I can easily show data related to Alaska and Hawaii with the continental US?
Something like this image
Don't believe my existing code is necessarily helpful, but here's how I build my base map (removed my custom style so that anyone should be able to generate).
fig = px.choropleth_mapbox(
df_mar,
geojson=puma,
locations="stpuma",
color="inter_pct",
range_color=(0,25),
color_continuous_scale="Viridis",
labels={"inter_pct": "Marriage (%)"},
center={"lat": 37.0902, "lon": -95.7129},
zoom=4.2,
opacity=1.0,
mapbox_style="white-bg"
)
fig.update_layout(
coloraxis_colorbar=dict(
bgcolor="rgba(22,33,49,1)",
title="Marriage,<br>Percent Share",
titlefont=dict(
color="rgba(255,255,255,1)"
),
tickfont=dict(
color="rgba(255,255,255,1)"
),
),
margin=dict(
l=50,
r=50,
b=50,
t=50,
pad=4
),
paper_bgcolor = "rgba(8,18,23,1)",
plot_bgcolor = "rgba(8,18,23,1)",
showlegend = True,
annotations = [
dict(
x=-0.025,
y=-0.04,
xref='paper',
yref='paper',
text='Source: Census ACS 5 2015-2019',
showarrow = False,
font=dict(
color="rgba(255,255,255,1)"
),
bgcolor="rgba(8,18,23,1)",
)
]
)
fig.update_traces(
marker_line_width=0,
below="waterway"
)
fig.show(width=1920, height=1080)
it can be achieved with mapbox
key concept is modify geometry to meet you layout requirements. Hence have done https://shapely.readthedocs.io/en/stable/manual.html#affine-transformations to move Alaska and Hawaii
also found that Alaska geometry was give issues given it crosses date line. Hence clipped geometry after transformation as well
for good measure added layers to indicate geometry has been manipulated
included maritime boundary to demonstrate how it can be extended to additional geometries
import geopandas as gpd
import shapely.geometry
import numpy as np
import plotly.express as px
import requests, io
from pathlib import Path
from zipfile import ZipFile
import urllib
import pandas as pd
from shapely.affinity import affine_transform as T
# US geometry
urls = [
"https://www2.census.gov/geo/tiger/GENZ2018/shp/cb_2018_us_state_5m.zip",
"https://maritimeboundaries.noaa.gov/downloads/USMaritimeLimitsAndBoundariesSHP.zip",
]
gdfs = {}
for url in urls:
f = Path.cwd().joinpath(urllib.parse.urlparse(url).path.split("/")[-1])
if not f.exists():
r = requests.get(url, stream=True, headers={"User-Agent": "XY"})
with open(f, "wb") as fd:
for chunk in r.iter_content(chunk_size=128):
fd.write(chunk)
zfile = ZipFile(f)
zfile.extractall(f.stem)
gdfs[f.stem] = gpd.read_file(
list(f.parent.joinpath(f.stem).glob("*.shp"))[0]
) # .to_crs("EPSG:4326")
gdf2 = gdfs["cb_2018_us_state_5m"]
gdf2 = gdf2.set_index("STUSPS", drop=False)
gdf2["color"] = gdf2["STATEFP"].astype(int)
# move alaska and hawaii using affine transform
t = {"AK": [0.6, 0, 0, 0.6, -20, -15], "HI": [3, 0, 0, 3, 385, -42]}
clip = (-179, 15, 0, 150)
gdf3 = gdf2.copy()
gdf3.loc[t.keys(), "geometry"] = gdf3.loc[t.keys(), ["geometry"]].apply(
lambda g: shapely.ops.clip_by_rect(T(g["geometry"], t[g.name]), *clip), axis=1
)
gdf_m = gdfs["USMaritimeLimitsAndBoundariesSHP"]
gdf_m = gdf_m.dissolve("REGION")
tm = {"Alaska": "AK", "Hawaiian Islands": "HI"}
gdf_m.loc[tm.keys(), "geometry"] = gdf_m.loc[tm.keys(), ["geometry"]].apply(
lambda g: shapely.ops.clip_by_rect(
T(g["geometry"], t[tm[g.name]]), *gdf3.loc[tm[g.name]].geometry.bounds
),
axis=1,
)
px.choropleth_mapbox(
gdf3,
geojson=gdf3.geometry.__geo_interface__,
locations=gdf3.index,
color="color",
hover_name="NAME",
).update_layout(
mapbox={
"style": "carto-positron",
"center": {"lon": -98, "lat": 33},
"zoom": 2.5,
"layers": [
{
"source": shapely.geometry.box(
*gdf3.loc[box].geometry.bounds
).__geo_interface__,
"type": "fill",
"color": "blue",
"opacity": 0.1,
}
for box in t.keys()
]
+ [
{
"source": gdf_m.geometry.__geo_interface__,
"type": "line",
"color": "blue",
"line": {"width": 1},
}
],
},
margin={"l": 0, "r": 0, "t": 0, "b": 0},
)
Related
I am rendering a scattermapbox using plotly in my Flask / Dash Application. I have set a default zoom level and lat,long coords. As the user pans the map via the plotly interface and changes the zoom level, I'd like to update the map with points and data layer.
Here's some code for reference:
import pandas as pd
import geopandas as gpd
# import mapbox
import requests
import plotly.graph_objects as go
# Update with host url
df_geo = gpd.GeoDataFrame.from_features(
requests.get(
"https://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_050_00_20m.json"
).json()
)
import plotly.graph_objects as go
fig = go.Figure(
go.Choroplethmapbox(
geojson=df_geo.set_index("GEO_ID")["geometry"].__geo_interface__,
locations=df_geo["GEO_ID"],
z=df_geo["CENSUSAREA"],
autocolorscale=False,
colorscale="Viridis",
zmin=df_geo["CENSUSAREA"].min(),
zmax=df_geo["CENSUSAREA"].quantile(0.95),
marker_line_width=0,
colorbar={"orientation": "h", "x": 0.5, "yanchor": "middle", "y": 0.1},
)
)
fig.update_layout(
mapbox_style="carto-positron",
# mapbox_accesstoken=token,
mapbox_zoom=3,
mapbox_center={"lat": 37.0902, "lon": -95.7129},
margin={"r": 0, "t": 0, "l": 0, "b": 0},
)
fig.show()
My question is, how do I obtain the geometries / bbox or lat,longs coords of the current map view?
Links to docs for reference:
https://plotly.com/python/reference/#scattermapbox
https://dash.plotly.com/dash-core-components/graph
relayoutData on a mapbox does return center and coordinates
have demonstrated by inserting this into trace using client side callback. This is working, however to improve efficiency I really wants to just update the figure rather than re-render it.
import pandas as pd
import geopandas as gpd
import requests
import plotly.graph_objects as go
from jupyter_dash import JupyterDash
import dash
from dash.dependencies import Input, Output, State
import json
# Update with host url
df_geo = gpd.GeoDataFrame.from_features(
requests.get(
"https://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_050_00_20m.json"
).json()
)
fig = go.Figure(
[
go.Choroplethmapbox(
geojson=df_geo.set_index("GEO_ID")["geometry"].__geo_interface__,
locations=df_geo["GEO_ID"],
z=df_geo["CENSUSAREA"],
autocolorscale=False,
colorscale="Viridis",
zmin=df_geo["CENSUSAREA"].min(),
zmax=df_geo["CENSUSAREA"].quantile(0.95),
marker_line_width=0,
name="choropleth"
# colorbar={"orientation": "h", "x": 0.5, "yanchor": "middle", "y": 0.1},
),
go.Scattermapbox(
name="scatter", marker={"size": 30, "color": "red", "opacity": 1}
),
]
)
fig.update_layout(
mapbox_style="carto-positron",
# mapbox_accesstoken=token,
mapbox_zoom=3,
mapbox_center={"lat": 37.0902, "lon": -95.7129},
margin={"r": 0, "t": 0, "l": 0, "b": 0},
datarevision=0,
height=300,
width=600,
autosize=False,
)
# Build App
app = JupyterDash(__name__)
app.layout = dash.html.Div(
[
dash.dcc.Checklist(
options=[{"label":"refesh", "value":"yes"}],
id="refresh",
),
dash.dcc.Graph(id="mapbox_fig", figure=fig),
dash.html.Div(
id="debug_container",
),
dash.dcc.Store(
id="points-store",
data={
"lat": [],
"lon": [],
},
),
]
)
#app.callback(
Output("points-store", "data"),
Output("debug_container", "children"),
Input("mapbox_fig", "relayoutData"),
Input("refresh","value")
)
def mapbox_cb(mapbox_cfg, refresh):
try:
refresh = refresh[0]=="yes"
except Exception:
refresh = False
if mapbox_cfg and "mapbox.zoom" in mapbox_cfg.keys() and refresh:
bbox = np.array(mapbox_cfg["mapbox._derived"]["coordinates"])
# bbox = bbox * .8
data = {
"lon": bbox[:, 0].tolist() + [mapbox_cfg["mapbox.center"]["lon"]],
"lat": bbox[:, 1].tolist() + [mapbox_cfg["mapbox.center"]["lat"]],
}
return data, [
dash.html.Pre(json.dumps(mapbox_cfg, indent=2)),
dash.html.Pre(json.dumps(data, indent=2)),
]
else:
raise dash.exceptions.PreventUpdate
app.clientside_callback(
"""
function(data, fig) {
fig.data[1]['lat'] = data['lat'];
fig.data[1]['lon'] = data['lon'];
fig.layout.datarevision = fig.layout.datarevision + 1;
/* return fig; */
return JSON.parse(JSON.stringify(fig));
}
""",
Output("mapbox_fig", "figure"),
Input("points-store", "data"),
State("mapbox_fig", "figure"),
)
app.run_server(mode="inline")
Thanks to Rob Raymond for the previos work. The aim is to represent the regions of a country with scatter_mapbox, I got this situation of the map (Spain is the example):
import requests
import plotly.express as px
import pandas as pd
# get Spain municipal boundaries
res = requests.get(
"https://raw.githubusercontent.com/codeforgermany/click_that_hood/main/public/data/spain-provinces.geojson"
)
# get some cities in Spain
df = (
pd.json_normalize(
requests.get(
"https://opendata.arcgis.com/datasets/6996f03a1b364dbab4008d99380370ed_0.geojson"
).json()["features"]
)
.loc[
lambda d: d["properties.CNTRY_NAME"].eq("Spain"),
["properties.CITY_NAME", "geometry.coordinates"],
]
.assign(
lon=lambda d: d["geometry.coordinates"].apply(lambda v: v[0]),
lat=lambda d: d["geometry.coordinates"].apply(lambda v: v[1]),
)
)
# scatter the cities and add layer that shows municiple boundary
px.scatter_mapbox(df, lat="lat", lon="lon", hover_name="properties.CITY_NAME").update_layout(
mapbox={
"style": "carto-positron",
"zoom": 3.5,
"layers": [
{
"source": res.json(),
"type": "line",
"color": "green",
"line": {"width": 1},
}
],
}
)
How to change cities by regions?
using geopandas https://plotly.com/python/mapbox-county-choropleth/#using-geopandas-data-frames
have created a column measure to define colorscale of province
simple case of doing choropleth instead of scatter
same can be achieved without geopandas referencing geojson and using pandas
import plotly.express as px
import numpy as np
import geopandas as gpd
gdf = gpd.read_file(
"https://raw.githubusercontent.com/codeforgermany/click_that_hood/main/public/data/spain-provinces.geojson",
crs="epsg:4326",
)
# for choropleth...
gdf["measure"] = np.random.randint(1, 1000, len(gdf))
px.choropleth_mapbox(
gdf, geojson=gdf["geometry"].__geo_interface__, locations=gdf.index, color="measure", hover_name="name"
).update_layout(
mapbox={
"style": "carto-positron",
"center": {
"lon": sum(gdf.total_bounds[[0, 2]]) / 2,
"lat": sum(gdf.total_bounds[[1, 3]]) / 2,
},
"zoom":4
},
margin={"l":0,"r":0,"t":0,"b":0}
)
I am rendering a map using mapbox API and would like to enrich the map by displaying additional location / POI data.
Here's a similar example: https://github.com/patelnisarg61/Toronto-Fatal-Collisions-Analysis/blob/master/collision.py
mock code below:
MAPBOX_KEY = "xxxxx"
data = []
data.append({
"type": "scattermapbox",
"lat": df["Lat"],
"lon": df["Long"],
"name": "Location",
"hovertext": name,
"showlegend": False,
"hoverinfo": "text",
"mode": "markers",
"clickmode": "event+select",
"marker": {
"symbol": "circle",
"size": 12,
"opacity": 0.7,
"color": "black"
}
}
)
layout = {
"autosize": True,
"hovermode": "closest",
"mapbox": {
"accesstoken": MAPBOX_KEY,
"bearing": 0,
"center": {
"lat": layout_lat,
"lon": layout_lon
},
"pitch": 0,
"zoom": zoom,
"style": "outdoors",
},
"margin": {
"r": 0,
"t": 0,
"l": 0,
"b": 0,
"pad": 0
}
}
How do I add additional POI data such as transit, hospitals, schools and grocery stores using either native mapbox API endpoints or data from other providers such as OSM / Google Maps?
For reference, this data is available via the OSM Feed: https://docs.mapbox.com/vector-tiles/reference/mapbox-streets-v8/
Plotly scattermapbox docs: https://plotly.com/python/reference/#scattermapbox-customdata
I used the example in the official reference as a basis, and the data used in the similar question. In this data, the data with bicycles in the 'VEHTYPE' column was extracted and used as the data for the graph. You will need a mapbox access token for this graph. For more information about markers, please refer to this page. However, it seems that not all icons can be used.
import plotly.graph_objects as go
import pandas as pd
url = 'https://raw.githubusercontent.com/patelnisarg61/Toronto-Fatal-Collisions-Analysis/master/Fatal_Collisions.csv'
df = pd.read_csv(url, sep=',')
df_bicycle = df[df['VEHTYPE'] == 'Bicycle']
mapbox_access_token = open("./mapbox_api_key.txt").read()
fig = go.Figure(go.Scattermapbox(
mode = "markers+text",
lon = df_bicycle['X'],
lat = df_bicycle['Y'],
marker = {'size': 15, 'symbol': ["bicycle"]*len(df_bicycle)},
text = ["Bicycle"]*len(df_bicycle),
textposition = "bottom right"))
fig.update_layout(
autosize=False,
height=600,
width=1000,
mapbox=dict(
accesstoken=mapbox_access_token,
style="streets",
center=dict(
lat=df_bicycle['Y'].mean(),
lon=df_bicycle['X'].mean()
),
zoom=10,
pitch=0),
showlegend=False)
fig.show()
Can somebody give me a hint of why this part of my go.Choropleth code is not working?
I'm trying to make my country's borders a little more thicker and black, but it's not working and I don't know what else I could be missing on this layout specs... Here is my map code section and below it you can check a zoomed part of the map generated. Notice the country's borders are still thin and grey, why it does not change?
map_fig_layout = {'coloraxis_colorbar': {'title': 'População (%)',
'thickness': 20,
'ticklabelposition':'outside bottom'},
'margin': {'r':0, 'l':0, 't':0, 'b':0},
'template': 'plotly_dark',
'geo':{'projection': go.layout.geo.Projection(type ='natural earth'),
'landcolor': '#262626',
'showcountries':True,
'showsubunits':True,
'subunitcolor': 'black',
'subunitwidth': 4,
'resolution':110,
'visible':True,
'countrywidth': 4,
'countrycolor' : 'black'},
'uirevision':'not_tracked_key'}
map_graph = go.Figure({'data':[ go.Choropleth(locations = dff['Code'],
z = dff['população_%'], # a column of dff
hovertext = dff['Entity'],
zmin = 0,
zmax = 100,
colorscale = make_colorscale( ['#F53347','#E6C730','#2FF5A8'] ),
geo = 'geo') ],
'layout': map_fig_layout})
Try adding this line to your code:
fig.update_traces(marker_line_width=2.0, selector=dict(type='choropleth'))
or in your case:
map_graph.update_traces(marker_line_width=2.0, selector=dict(type='choropleth'))
You can additionally control the opacity, if so desired:
E.g.,
from urllib.request import urlopen
import json
with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
counties = json.load(response)
import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv",
dtype={"fips": str})
import plotly.express as px
fig = px.choropleth(df, geojson=counties, locations='fips', color='unemp',
color_continuous_scale="Viridis",
range_color=(0, 12),
scope="usa",
labels={'unemp':'unemployment rate'}
)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.update_traces(marker_line_width=3.0, marker_opacity=0.6, selector=dict(type='choropleth'))
fig.show()
Docs References
https://plotly.com/python/reference/choropleth/#choropleth-marker
using your code (make sure you format it to be PEP8 compliant for future questions)
sourced some data from kaggle to make this a re-producible example
examples of subunits are counties / regions in a country
import kaggle.cli
import sys, requests
import pandas as pd
from pathlib import Path
from zipfile import ZipFile
import urllib
import plotly.graph_objects as go
from plotly.colors import make_colorscale
# fmt: off
# download data set
url = "https://www.kaggle.com/mohaiminul101/population-growth-annual"
sys.argv = [sys.argv[0]] + f"datasets download {urllib.parse.urlparse(url).path[1:]}".split(" ")
kaggle.cli.main()
zfile = ZipFile(f'{urllib.parse.urlparse(url).path.split("/")[-1]}.zip')
dfs = {f.filename: pd.read_csv(zfile.open(f)) for f in zfile.infolist()}
# fmt: on
dff = dfs["world_population_growth.csv"].rename(
columns={"Country Code": "Code", "2019": "população_%", "Country Name": "Entity"}
)
dff["população_%"] = dff["população_%"] * 100
map_fig_layout = {
"coloraxis_colorbar": {
"title": "População (%)",
"thickness": 20,
"ticklabelposition": "outside bottom",
},
"margin": {"r": 0, "l": 0, "t": 0, "b": 0},
"template": "plotly_dark",
"geo": {
"projection": go.layout.geo.Projection(type="natural earth"),
"resolution": 110,
"visible": True,
},
"uirevision": "not_tracked_key",
}
map_graph = go.Figure(
{
"data": [
go.Choropleth(
locations=dff["Code"],
z=dff["população_%"], # a column of dff
hovertext=dff["Entity"],
zmin=0,
zmax=100,
marker={"line":{"width":4, "color":"black"}},
colorscale=make_colorscale(["#F53347", "#E6C730", "#2FF5A8"]),
)
],
"layout": map_fig_layout,
}
)
map_graph
I am using plotlys scattermapbox to plot points on a map. I'd like to draw the polygon that cover 'x' mile radius from a POI.
dcc.Graph(id="map-graph"),
#application.callback([
Output("map-graph", "figure"),
],
[
Input("address", "value"),
Input("type", "value")
]
)
def update_graph(address, type):
for i, row in df.iterrows():
lat = row["Lat"]
lng = row["Long"]
data.append({
"type": "scattermapbox",
"lat": [lat],
"lon": [lng],
"name": "Location",
"showlegend": False,
"hoverinfo": "text",
"mode": "markers",
"marker": {
"symbol": "circle",
"size": 8,
"opacity": 0.8,
"color": "black"
}
}
)
# Plot POI
POI_Lat = 37.785908
POI_Long = -122.400803
data.append({
"type": "scattermapbox",
"lat": [POI_Lat],
"lon": [POI_Long],
"marker": {
"symbol": "circle,
"size": 28,
"opacity": 0.7,
"color": "rgb(128, 128, 128)"
}
}
)
df is a pandas dataframe that includes coordinates for locations within x miles of POI. How do I update the map-graph to draw a polygon that covers all the points?
Adding a layer to layout dictionary:
gdf = circles(Lat, Long, radius=1609.34)
print(gdf['geometry'][0])
POLYGON ((385272.0167249573 3768678.19769511, 385264.2673129799 3768520.454790493,.......))
layout = {
"autosize": True,
"hovermode": "closest",
"mapbox": {
"accesstoken": MAPBOX_KEY,
"bearing": 0,
"center": {
"lat": layout_lat,
"lon": layout_lon
},
"layers": [
{
"source": json.loads(gdf.geometry.to_json()),
"below": "traces",
"type": "line",
"color": "purple",
"line": {"width": 1.5},
}
],
"pitch": 0,
"zoom": zoom,
"style": "outdoors",
},
"margin": {
"r": 0,
"t": 0,
"l": 0,
"b": 0,
"pad": 0
}
}
based on answer to this duplicate question Obtain coordinates of a Polygon / Multi-polygon around a point in python
no sample data provided in question, so I've used UK hospital data
have created a helper function poi_poly(). NB radius is in meters as per UTM geometry
UTM geometry is used to create a polygon of specified radius
markers are then intersected with this polygon. Then get the convex hull
have provided option to return radius polygon as well, in example below I've returned this to demonstrate that the convex hull polygon is within the radius of the POI
import shapely.geometry
import pandas as pd
import geopandas as gpd
import requests, io, json
import plotly.express as px
import random
def poi_poly(
df,
radius=10 ** 5,
poi={"Longitude": 0.06665166467428207, "Latitude": 51.19034957885742},
lon_col="Longitude",
lat_col="Latitude",
include_radius_poly=False,
):
# generate a geopandas data frame of the POI
gdfpoi = gpd.GeoDataFrame(
geometry=[shapely.geometry.Point(poi["Longitude"], poi["Latitude"])],
crs="EPSG:4326",
)
# extend point to radius defined (a polygon). Use UTM so that distances work, then back to WSG84
gdfpoi = (
gdfpoi.to_crs(gdfpoi.estimate_utm_crs())
.geometry.buffer(radius)
.to_crs("EPSG:4326")
)
# create a geopandas data frame of all the points / markers
if not df is None:
gdf = gpd.GeoDataFrame(
geometry=df.loc[:, ["Longitude", "Latitude"]]
.dropna()
.apply(
lambda r: shapely.geometry.Point(r["Longitude"], r["Latitude"]), axis=1
)
.values,
crs="EPSG:4326",
)
else:
gdf = gpd.GeoDataFrame(geometry=gdfpoi)
# create a polygon around the edges of the markers that are within POI polygon
return pd.concat(
[
gpd.GeoDataFrame(
geometry=[
gpd.sjoin(
gdf, gpd.GeoDataFrame(geometry=gdfpoi), how="inner"
).unary_union.convex_hull
]
),
gpd.GeoDataFrame(geometry=gdfpoi if include_radius_poly else None),
]
)
# 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",
)
# generate polygon of markers within 5 mile radius of Point of Interest
poi = dfhos.loc[random.randint(0, len(dfhos) - 1), ["Longitude", "Latitude"]].to_dict()
gdf = poi_poly(dfhos, poi=poi, radius=1609.34 * 5, include_radius_poly=True)
fig = (
px.scatter_mapbox(
dfhos,
lat="Latitude",
lon="Longitude",
color="Sector",
hover_data=["OrganisationName", "Postcode"],
)
.update_traces(marker={"size": 10})
.update_layout(
mapbox={
"style": "open-street-map",
"zoom": 9,
"center": {"lat": poi["Latitude"], "lon": poi["Longitude"]},
"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()
draw just a circle polygon
poi_poly() has been updated. DataFrame is no longer mandatory for finding markers within POI
simple example of creating a circle (actually a polygon) centred on a single set of GPS co-ordinates
import plotly.graph_objects as go
poi = {"Latitude": 37.785908, "Longitude": -122.400803}
go.Figure(go.Scattermapbox()).update_layout(
mapbox={
"style": "open-street-map",
"zoom": 9,
"center": {"lat": poi["Latitude"], "lon": poi["Longitude"]},
"layers": [
{
"source": json.loads(poi_poly(None, poi=poi, radius=1609).to_json()),
"below": "traces",
"type": "line",
"color": "purple",
"line": {"width": 1.5},
}
],
},
margin={"l": 0, "r": 0, "t": 0, "b": 0},
)
See an example in the documentation here
import plotly.graph_objects as go
fig = go.Figure(go.Scattermapbox(
mode = "markers",
lon = [-73.605], lat = [45.51],
marker = {'size': 20, 'color': ["cyan"]}))
fig.update_layout(
mapbox = {
'style': "stamen-terrain",
'center': { 'lon': -73.6, 'lat': 45.5},
'zoom': 12, 'layers': [{
'source': {
'type': "FeatureCollection",
'features': [{
'type': "Feature",
'geometry': {
'type': "MultiPolygon",
'coordinates': [[[
[-73.606352888, 45.507489991], [-73.606133883, 45.50687600],
[-73.605905904, 45.506773980], [-73.603533905, 45.505698946],
[-73.602475870, 45.506856969], [-73.600031904, 45.505696003],
[-73.599379992, 45.505389066], [-73.599119902, 45.505632008],
[-73.598896977, 45.505514039], [-73.598783894, 45.505617001],
[-73.591308727, 45.516246185], [-73.591380782, 45.516280145],
[-73.596778656, 45.518690062], [-73.602796770, 45.521348046],
[-73.612239983, 45.525564037], [-73.612422919, 45.525642061],
[-73.617229085, 45.527751983], [-73.617279234, 45.527774160],
[-73.617304713, 45.527741334], [-73.617492052, 45.527498362],
[-73.617533258, 45.527512253], [-73.618074188, 45.526759105],
[-73.618271651, 45.526500673], [-73.618446320, 45.526287943],
[-73.618968507, 45.525698560], [-73.619388002, 45.525216750],
[-73.619532966, 45.525064183], [-73.619686662, 45.524889290],
[-73.619787038, 45.524770086], [-73.619925742, 45.524584939],
[-73.619954486, 45.524557690], [-73.620122362, 45.524377961],
[-73.620201713, 45.524298907], [-73.620775593, 45.523650879]
]]]
}
}]
},
'type': "fill", 'below': "traces", 'color': "royalblue"}]},
margin = {'l':0, 'r':0, 'b':0, 't':0})
fig.show()
Adjust the above based on your point and polygon coordinates.
If you want to use another mapbox style:
The accepted values for layout.mapbox.style are one of:
"white-bg" yields an empty white canvas which results in no external HTTP requests
"open-street-map", "carto-positron", "carto-darkmatter", "stamen-terrain",
"stamen-toner" or "stamen-watercolor" yield maps composed of raster tiles from various public tile servers which do not require signups or access tokens
"basic", "streets", "outdoors", "light", "dark", "satellite", or "satellite-streets" yield maps composed of vector tiles from the Mapbox service, and do require a Mapbox Access Token or an on-premise Mapbox installation.
A Mapbox service style URL, which requires a Mapbox Access Token or an on-premise Mapbox installation.
A Mapbox Style object as defined at https://docs.mapbox.com/mapbox-gl-js/style-spec/
https://plotly.com/python/mapbox-layers/