Plotly Python如何给go.Scattermapbox添加ff.create_quiver风矢轨迹并正常显示
问题原因
- 核心问题是
ff.create_quiver生成的是普通笛卡尔坐标系的轨迹,不属于Plotly的*mapbox系列轨迹,无法匹配Mapbox的经纬度坐标系,也不会渲染在地图视图层上方,所以要么位置完全偏离可视区域,要么被地图层完全覆盖。 - 其次你的矢量网格坐标是0-2的数值,没有和实际经纬度范围做映射,就算坐标系兼容也无法对应到地图的正确位置。
解决方案
- 先将你的矢量网格坐标映射到实际数据集的经纬度范围,同时将风分量u、v换算为经纬度的偏移量(注意1度纬度对应约111km,1度经度对应约111*cos(纬度)km,保证矢量方向比例正确)
- 手动构造每个风箭头的路径,使用
go.Scattermapbox类型的轨迹绘制,确保可以渲染在地图上方。 - 调整轨迹层级,后添加的风矢量轨迹默认会在最早添加的散点轨迹上方,也可以通过
layer参数指定显示层级。
修改后的代码示例:
import plotly.graph_objects as go import numpy as np import pandas as pd # 假设你的df已存在,先计算经纬度范围 lon_min, lon_max = df['lon'].min(), df['lon'].max() lat_min, lat_max = df['lat'].min(), df['lat'].max() # 生成网格并映射到经纬度范围 x_grid, y_grid = np.meshgrid(np.arange(0,2,.2), np.arange(0,2,.2)) # 映射x到经度,y到纬度 lon_grid = lon_min + (x_grid / 2) * (lon_max - lon_min) lat_grid = lat_min + (y_grid / 2) * (lat_max - lat_min) # 计算风分量 u = np.cos(x_grid) * y_grid v = np.sin(x_grid) * y_grid # 风矢量缩放系数,可根据实际显示效果调整 scale = 0.1 # 存储所有箭头的坐标,None用于分隔不同箭头的路径 arrow_lons = [] arrow_lats = [] for i in range(lon_grid.shape[0]): for j in range(lon_grid.shape[1]): # 起点经纬度 start_lon = lon_grid[i,j] start_lat = lat_grid[i,j] # 终点经纬度,换算经度偏移时乘以cos(纬度)保证比例正确 end_lon = start_lon + u[i,j] * scale / np.cos(np.radians(start_lat)) end_lat = start_lat + v[i,j] * scale # 添加箭身路径 arrow_lons.extend([start_lon, end_lon, None]) arrow_lats.extend([start_lat, end_lat, None]) # 可选:添加箭头尖,可根据需要调整角度和长度 arrow_size = 0.02 angle = np.arctan2(v[i,j], u[i,j]) # 箭头左侧 left_lon = end_lon - arrow_size * np.cos(angle + np.pi/6) / np.cos(np.radians(end_lat)) left_lat = end_lat - arrow_size * np.sin(angle + np.pi/6) # 箭头右侧 right_lon = end_lon - arrow_size * np.cos(angle - np.pi/6) / np.cos(np.radians(end_lat)) right_lat = end_lat - arrow_size * np.sin(angle - np.pi/6) arrow_lons.extend([end_lon, left_lon, end_lon, right_lon, None]) arrow_lats.extend([end_lat, left_lat, end_lat, right_lat, None]) fig = go.Figure() # 先添加原始散点 fig.add_trace(go.Scattermapbox( mode = "markers", lon = df['lon'], lat = df['lat'], marker = {'size': 5, 'color':'black'}, )) # 再添加风矢量箭头,后添加的轨迹层级更高 fig.add_trace(go.Scattermapbox( mode = "lines", lon = arrow_lons, lat = arrow_lats, line = {'width': 1, 'color': 'red'}, hoverinfo = 'skip' )) fig.update_layout( margin={"l": 0, "r": 0, "t": 15, "b": 0}, mapbox={ "style": "carto-positron", "zoom": 5, "center": { "lon": df['lon'].mean(), "lat": df['lat'].mean(), }, }, ) fig.show()
可根据实际显示效果调整scale(风矢量长度)和arrow_size(箭头大小)参数。
内容的提问来源于stack exchange,提问作者lizard
相关产品推荐
相关产品推荐

