如何在插图上创建符号/按钮 [英] How to create a symbol/button on a Plotly choropleth map
本文介绍了如何在插图上创建符号/按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我希望在Ploly Choppleth地图上创建类似于地图https://resources-covid19canada.hub.arcgis.com/上的按钮(我的三个红色箭头所指向的)的按钮。单击该按钮时,将显示图例窗口。
我们非常感谢您的建议。
感谢您的帮助!
推荐答案
- 您可以使用绘图来实现您所显示的图形类型。在MapBox绘图上使用符号存在多个问题。因此,如果要设置颜色、调整大小和使用不同的形状,则必须使用Geojson图层
- 用类似的方式制作图例是不可能的。显然您有Colorbar图例。标记的大小和形状实际上取决于视觉方面,没有图例
- 完整代码在末尾
- 源数据
- 您链接的网站按省列出的加拿大COVID数据
- 加拿大省几何图形边界
- 准备数据。计算移动百分比
- 实用工具函数用于从https://labs.mapbox.com/maki-icons/或https://fontawesome.com/v5.15/icons?d=gallery&p=1&m=free源SVG
- 此代码可以进一步细化。缓存SVG文件,更佳的大小比例
- 源数据
px.choropleth_mapbox(
df.loc[df["SummaryDate"].eq(df["SummaryDate"].max())].merge(df_t, on="Abbreviation"),
geojson=gdf_can.geometry,
locations="Abbreviation",
color="DailyTotals",
hover_data={"Province":True, "SummaryDate":True, "Change":":.2%"},
color_continuous_scale="BuPu"
).update_layout(
mapbox={
"style": "carto-positron",
"zoom": 2,
"center": {
"lon": sum(gdf_can.total_bounds[[0, 2]]) / 2,
"lat": sum(gdf_can.total_bounds[[1, 3]]) / 2,
},
"layers": px_marker_mapbox(
df_t.join(gdf_can),
color_discrete_map={
"solid/arrow-up": "yellow",
"solid/arrow-down": "silver",
},
),
},
margin={"l": 0, "r": 0, "t": 0, "b": 0},
)
安装代码
import geopandas as gpd
import pandas as pd
import requests
import plotly.express as px
import shapely.geometry
import svgpath2mpl
import numpy as np
# create shapely multi-polygon from maki or font-awesome SVG path
def marker(name="star", source="fa"):
def to_shapely(mpl, simplify=0):
p = shapely.geometry.MultiPolygon(
[shapely.geometry.Polygon(a).simplify(simplify) for a in mpl]
)
p = shapely.affinity.affine_transform(
p,
[1, 0, 0, -1, 0, 0],
)
scale = 1 if source == "maki" else 10 ** -2
p = shapely.affinity.affine_transform(
p,
[1, 0, 0, 1, -p.centroid.x, -p.centroid.y],
)
return shapely.affinity.affine_transform(
p,
[scale, 0, 0, scale, -p.centroid.x, -p.centroid.y],
)
if source == "maki":
url = f"https://raw.githubusercontent.com/mapbox/maki/main/icons/{name}.svg"
elif source == "fa":
url = f"https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/svgs/{name}.svg"
svgpath = pd.read_xml(requests.get(url).text).loc[0, "d"]
return to_shapely(svgpath2mpl.parse_path(svgpath).to_polygons())
# create mapbox layers for markers. icon defines layer and color
def px_marker_mapbox(
df,
icon="icon",
size="size",
lat="lat",
lon="lon",
color_discrete_map=None,
color_discrete_sequence=px.colors.qualitative.Plotly,
):
layers = []
for i, g in enumerate(df.groupby(icon)):
m = marker(g[0])
geoms = [
shapely.affinity.affine_transform(
m, [r[1][size], 0, 0, r[1][size], r[1][lon], r[1][lat]]
)
for r in g[1].iterrows()
]
if color_discrete_map and g[0] in color_discrete_map.keys():
color = color_discrete_map[g[0]]
else:
color = color_discrete_sequence[i % len(color_discrete_sequence)]
layers.append(
{
"source": gpd.GeoSeries(geoms).__geo_interface__,
"type": "fill",
"color": color,
}
)
return layers
# fmt: off
gdf_can = gpd.GeoDataFrame.from_features(requests.get("https://data.opendatasoft.com/explore/dataset/georef-canada-province@public/download/?format=geojson&timezone=Europe/London&lang=en").json())
gdf_can["lat"] = gdf_can["geo_point_2d"].apply(lambda l: l[0])
gdf_can["lon"] = gdf_can["geo_point_2d"].apply(lambda l: l[1])
# two different province codes used by COVID and geometry, get map...
df_prov = pd.read_html("https://www150.statcan.gc.ca/n1/pub/92-195-x/2011001/geo/prov/tbl/tbl8-eng.htm")[0].drop(13)
df_prov = df_prov.rename(
columns={
"Internationally approved alpha code (Source: Canada Post)": "Abbreviation",
"Standard geographical classification (SGC) code": "prov_code",
}
)
gdf_can = gdf_can.merge(df_prov.loc[:, ["prov_code", "Abbreviation"]], on="prov_code").set_index("Abbreviation")
# get COVID daily data...
df = pd.json_normalize(requests.get("https://opendata.arcgis.com/datasets/3afa9ce11b8842cb889714611e6f3076_0.geojson").json()["features"])
df = df.rename(columns={c:c.split(".")[1] for c in df.columns if len(c.split("."))==2})
df["SummaryDate"] = pd.to_datetime(df["SummaryDate"].str[0:10]) if df["SummaryDate"].dtype=="O" else df["SummaryDate"]
df = df.loc[df["SummaryDate"].ge(df["SummaryDate"].max()-pd.Timedelta(days=7)) & df["Abbreviation"].ne("CA")]
# fmt: on
# rollup changes data...
df_t = df.groupby("Abbreviation")["DailyTotals"].apply(
lambda s: s.pct_change(periods=7).dropna()
).to_frame().rename(columns={"DailyTotals":"Change"}).assign(
icon=lambda d: np.select(
[d["Change"] < -0.1, d["Change"] > 0.1],
["solid/arrow-down", "solid/arrow-up"],
"solid/arrows-alt-h",
),
size=lambda d: d["Change"].abs()
).droplevel(1)
这篇关于如何在插图上创建符号/按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文