Plotly 中的插图 (Python)
Inset Maps in Plotly (Python)
我目前正尝试在 Python 中使用 Plotly Express 和 Mapbox 绘制一些地图。
我需要一张带有国家/地区的大地图,旁边是一张“缩放”到特定区域的插图(参见示例图片)INSET MAP EXAMPLE。
我设法绘制了更大的地图(即整个国家/地区),但找不到正确的方法来创建插图。
我尝试制作 2 个子图(1 行,2 列),但没有按预期工作。还尝试同时绘制两个图形(一个大一点,整个国家,一个小一点,插图),但他们两个“碰撞”(插图原来在另一个上面) .
对此有任何想法或可能的转变吗?
谢谢。
- 已使用 dash 启用主 choropeth 的回调以更新 inset choropeth(我构造 dash HTML 的方式意味着它开始了...)
- 为了将它们整合在一起,我使用了一些来自英国政府来源的地理映射数据
- 刚刚修改了 callback 中 choropeth 的 center。也可以修改 zoom and/or range
获取一些地理数据
import requests
import geopandas as gpd
import pandas as pd
# https://ons-inspire.esriuk.com/arcgis/rest/services/Administrative_Boundaries/Local_Authority_Districts_December_2017_Boundaries/MapServer/3/query?where=1%3D1&outFields=*&outSR=4326&f=json
# res = requests.get("https://opendata.arcgis.com/datasets/ae90afc385c04d869bc8cf8890bd1bcd_3.geojson")
res = requests.get(
"https://opendata.arcgis.com/datasets/69dc11c7386943b4ad8893c45648b1e1_0.geojson"
)
# use 2019 so Buckinghamshire is included
rescounties = requests.get(
"https://opendata.arcgis.com/datasets/37363d379f4f40fa8c3f0d28eedfdd37_0.geojson"
)
gdf = pd.concat(
[
gpd.GeoDataFrame.from_features(res.json()["features"], crs="CRS84")
.pipe(lambda d: d.rename(columns={c: c.lower() for c in d.columns}).drop(columns="lad20nmw"))
.rename(columns={"lad20cd": "areaCode", "lad20nm": "areaName"}),
gpd.GeoDataFrame.from_features(rescounties.json()["features"], crs="CRS84")
.pipe(lambda d: d.rename(columns={c: c.lower() for c in d.columns}))
.rename(columns={"cty19cd": "areaCode","cty20cd": "areaCode","cty19nm": "areaName","st_areashape": "shape__area",
"st_lengthshape": "shape__length",}),
]
).set_index("areaCode").assign(country=lambda d: d.index.str[0])
构建基础模型
import plotly.express as px
fig = px.choropleth_mapbox(
gdf,
geojson=gdf.geometry,
locations=gdf.index,
hover_name="areaName",
color="country",
color_discrete_sequence=["green", "yellow", "orange", "red", "magenta"],
center={"lat": (gdf.total_bounds[1] + gdf.total_bounds[3])/2, "lon": (gdf.total_bounds[0] + gdf.total_bounds[2])/2},
mapbox_style="carto-positron",
zoom=5,
).update_layout(margin={"l":0,"r":0,"b":0,"t":0})
达世币应用程序
import json
import numpy as np
import plotly.graph_objects as go
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
import dash_table
from dash.dependencies import Input, Output, State
from jupyter_dash import JupyterDash
ifig = go.Figure(fig.data).update_layout(fig.layout).update_layout(showlegend=False)
# Build App
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(
[
dbc.Row(
[
dbc.Col(
dcc.Graph(id="map", figure=fig, style={"height": "90vh"}),
width=9,
),
dbc.Col(
dcc.Graph(id="insetmap", style={"height": "25vh"}),
width=3,
),
]
),
],
style={"font-family": "Arial", "font-size": "0.9em"},
)
@app.callback(
Output("insetmap", "figure"),
Input("map", "selectedData"),
)
def mapSelect(selectData):
global ifig
if selectData and "range" in selectData.keys():
r = selectData["range"]["mapbox"]
ifig = ifig.update_layout(
mapbox={
"center": {
"lon": (r[0][0] + r[1][0]) / 2,
"lat": (r[0][1] + r[1][1]) / 2,
}
}
)
print(ifig.layout["mapbox"])
return ifig
return ifig
# Run app and display result inline in the notebook
app.run_server(mode="inline")
产出
我目前正尝试在 Python 中使用 Plotly Express 和 Mapbox 绘制一些地图。
我需要一张带有国家/地区的大地图,旁边是一张“缩放”到特定区域的插图(参见示例图片)INSET MAP EXAMPLE。
我设法绘制了更大的地图(即整个国家/地区),但找不到正确的方法来创建插图。
我尝试制作 2 个子图(1 行,2 列),但没有按预期工作。还尝试同时绘制两个图形(一个大一点,整个国家,一个小一点,插图),但他们两个“碰撞”(插图原来在另一个上面) .
对此有任何想法或可能的转变吗?
谢谢。
- 已使用 dash 启用主 choropeth 的回调以更新 inset choropeth(我构造 dash HTML 的方式意味着它开始了...)
- 为了将它们整合在一起,我使用了一些来自英国政府来源的地理映射数据
- 刚刚修改了 callback 中 choropeth 的 center。也可以修改 zoom and/or range
获取一些地理数据
import requests
import geopandas as gpd
import pandas as pd
# https://ons-inspire.esriuk.com/arcgis/rest/services/Administrative_Boundaries/Local_Authority_Districts_December_2017_Boundaries/MapServer/3/query?where=1%3D1&outFields=*&outSR=4326&f=json
# res = requests.get("https://opendata.arcgis.com/datasets/ae90afc385c04d869bc8cf8890bd1bcd_3.geojson")
res = requests.get(
"https://opendata.arcgis.com/datasets/69dc11c7386943b4ad8893c45648b1e1_0.geojson"
)
# use 2019 so Buckinghamshire is included
rescounties = requests.get(
"https://opendata.arcgis.com/datasets/37363d379f4f40fa8c3f0d28eedfdd37_0.geojson"
)
gdf = pd.concat(
[
gpd.GeoDataFrame.from_features(res.json()["features"], crs="CRS84")
.pipe(lambda d: d.rename(columns={c: c.lower() for c in d.columns}).drop(columns="lad20nmw"))
.rename(columns={"lad20cd": "areaCode", "lad20nm": "areaName"}),
gpd.GeoDataFrame.from_features(rescounties.json()["features"], crs="CRS84")
.pipe(lambda d: d.rename(columns={c: c.lower() for c in d.columns}))
.rename(columns={"cty19cd": "areaCode","cty20cd": "areaCode","cty19nm": "areaName","st_areashape": "shape__area",
"st_lengthshape": "shape__length",}),
]
).set_index("areaCode").assign(country=lambda d: d.index.str[0])
构建基础模型
import plotly.express as px
fig = px.choropleth_mapbox(
gdf,
geojson=gdf.geometry,
locations=gdf.index,
hover_name="areaName",
color="country",
color_discrete_sequence=["green", "yellow", "orange", "red", "magenta"],
center={"lat": (gdf.total_bounds[1] + gdf.total_bounds[3])/2, "lon": (gdf.total_bounds[0] + gdf.total_bounds[2])/2},
mapbox_style="carto-positron",
zoom=5,
).update_layout(margin={"l":0,"r":0,"b":0,"t":0})
达世币应用程序
import json
import numpy as np
import plotly.graph_objects as go
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
import dash_table
from dash.dependencies import Input, Output, State
from jupyter_dash import JupyterDash
ifig = go.Figure(fig.data).update_layout(fig.layout).update_layout(showlegend=False)
# Build App
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(
[
dbc.Row(
[
dbc.Col(
dcc.Graph(id="map", figure=fig, style={"height": "90vh"}),
width=9,
),
dbc.Col(
dcc.Graph(id="insetmap", style={"height": "25vh"}),
width=3,
),
]
),
],
style={"font-family": "Arial", "font-size": "0.9em"},
)
@app.callback(
Output("insetmap", "figure"),
Input("map", "selectedData"),
)
def mapSelect(selectData):
global ifig
if selectData and "range" in selectData.keys():
r = selectData["range"]["mapbox"]
ifig = ifig.update_layout(
mapbox={
"center": {
"lon": (r[0][0] + r[1][0]) / 2,
"lat": (r[0][1] + r[1][1]) / 2,
}
}
)
print(ifig.layout["mapbox"])
return ifig
return ifig
# Run app and display result inline in the notebook
app.run_server(mode="inline")