Plotly:如何绘制箭头线(有向图)?
Posted
技术标签:
【中文标题】Plotly:如何绘制箭头线(有向图)?【英文标题】:Plotly: How to plot arrow line (directed graph)? 【发布时间】:2022-01-13 10:10:01 【问题描述】:我想在节点之间绘制一条箭头线来指示路线的方向。我找不到这样做的内置函数。有什么方法可以完成这项工作吗?
我的代码:
import plotly.graph_objects as go
import plotly.io as pio
import plotly
lon1 = [113.076843, 113.154191, 113.737213, 113.842405, 114.244183 ]
lat1 = [23.10993, 23.218533, 23.047626, 22.987975, 22.601581 ]
lon2 = [113.364738, 113.664108, 113.661705,114.244183]
lat2 = [22.997112, 22.878038, 22.869216, 22.601581]
lon_trip1 = lon1
lat_trip1 = lat1
lon_trip2 = lon2
lat_trip2 = lat2
fig = go.Figure()
fig.add_trace(go.Scattermapbox(
mode="markers+lines",
lon=lon_trip1,
lat=lat_trip1,
name="trip1", marker='size': 10))
fig.add_trace(
go.Scattermapbox(
mode="markers+lines",
lon=lon_trip2,
lat=lat_trip2,
name="trip2",
marker='size': 10))
fig.update_layout(
margin='l': 113, 't': 24, 'b': 22, 'r': 115,
mapbox=dict(style='carto-positron',
center=go.layout.mapbox.Center(lon=113.664, lat=22.878),
pitch=0,
zoom=8)
)
pio.write_image(fig,'C:/Users/Jie/Desktop/plot.png',width=1980, height=1080)
#plotly.offline.plot(fig, filename='C:/Users/user/Desktop/plot' + '.html')
fig.show()
另外,我想在真实世界地图上进一步添加networkx图。是否可以使用 plotly 将地图图层添加到原始 networkx 图中?
完整代码在这里: Plot Networkx graph on a real world map
【问题讨论】:
【参考方案1】: 您可以将 geojson 图层添加到 mapbox 人物 这种方法会在每条线段的中间创建一个标记以显示行进方向 使用高中三角学旋转标记以计算行进角度 具有基于 cmets 的扩展解决方案。现在可以使用place
参数请求放置。图片显示beyond选项包括center、end、beyond
代码
import plotly.graph_objects as go
import plotly.express as px
import plotly.io as pio
import plotly
import math
import shapely.geometry
from shapely.affinity import rotate as R, translate as T
lon1 = [113.076843, 113.154191, 113.737213, 113.842405, 114.244183]
lat1 = [23.10993, 23.218533, 23.047626, 22.987975, 22.601581]
lon2 = [113.364738, 113.664108, 113.661705, 114.244183]
lat2 = [22.997112, 22.878038, 22.869216, 22.601581]
lon_trip1 = lon1
lat_trip1 = lat1
lon_trip2 = lon2
lat_trip2 = lat2
fig = go.Figure()
fig.add_trace(
go.Scattermapbox(
mode="markers+lines",
lon=lon_trip1,
lat=lat_trip1,
name="trip1",
marker="size": 10,
)
)
fig.add_trace(
go.Scattermapbox(
mode="markers+lines",
lon=lon_trip2,
lat=lat_trip2,
name="trip2",
marker="size": 10,
)
)
# create a mapbox layer that are arrows that show direction between sequence of lat / lon pairs
def direction(lat1, lon1, marker=None, color="yellow", place="center"):
# default marker is a left pointing arrow, centred as 0,0
# it may be necessary to adjust sizing
if marker is None:
m = R(shapely.geometry.Polygon([(0, 0), (0, 1), (0.5, 0.5)]), 0)
m = shapely.affinity.scale(m, xfact=0.05, yfact=0.05) # size appropriately
m = T(m, -m.centroid.x, -m.centroid.y)
else:
m = marker
def place_marker(m, x1, x0, y1, y0, place=place):
theta = math.atan2(x1 - x0, y1 - y0)
if place == "center":
p = dict(
xoff=(y1 - y0) / 2 + y0,
yoff=(x1 - x0) / 2 + x0,
)
elif place == "end":
p = dict(xoff=y1, yoff=x1)
elif place == "beyond":
H = .05
p = dict(xoff=y1 + math.cos(theta)*H, yoff=x1 + math.sin(theta)*H)
return T(R(m, theta, use_radians=True), **p)
return
# list of geometries rotated based on direction and centred on line between pairs of points
"source": shapely.geometry.MultiPolygon(
[
place_marker(m, x1, x0, y1, y0)
for x0, x1, y0, y1 in zip(lat1, lat1[1:], lon1, lon1[1:])
]
).__geo_interface__,
"type": "fill",
"color": color,
"below":"traces"
fig.update_layout(
margin="l": 113, "t": 24, "b": 22, "r": 115,
mapbox=dict(
style="carto-positron",
center=go.layout.mapbox.Center(lon=113.664, lat=22.878),
pitch=0,
zoom=8,
layers=[
direction(t.lat, t.lon, marker=None, color=c, place="beyond")
for t, c in zip(fig.data, px.colors.qualitative.Plotly)
],
),
)
【讨论】:
感谢您的帮助。是否可以将箭头定位在行尾而不是中间,就像普通的箭头线一样? 是的 - 已更新以提供这种灵活性。 由于某种原因,我的机器无法安装 geopandas。刚找到这个直接画图的方法:community.plotly.com/t/…不知道行不行。 plotly.com/python/map-configuration mapbox 和 geo 使用起来完全不同......你的机器上安装了吗?我已经删除了对 geopandas 的依赖 亲爱的 Rob 非常感谢。这好多了。如何调整箭头以使其不与节点重叠,即(将箭头移到节点前面而不在它上面)?我在节点上显示了数字,如果它们重叠,将被覆盖。以上是关于Plotly:如何绘制箭头线(有向图)?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 plotly.graph_objects 绘制 3D 线?
如何根据不同的dataFrame部分绘制(plotly.express)多条线