#python #plotly #plotly-python
#python #plotly #plotly-python
Вопрос:
Я пытаюсь добавить векторы ветра на свою карту Plotly. Это упрощенная версия кода:
import plotly.graph_objects as go
import plotly.figure_factory as ff
fig = go.Figure(go.Scattermapbox(
mode = "markers",
lon = df['lon'],
lat = df['lat'],
marker = {'size': 5, 'color':'black'},
x, y = np.meshgrid(np.arange(0,2,.2), np.arange(0,2,.2))
u = np.cos(x) * y
v = np.sin(x) * y
vec_field = ff.create_quiver(x, y, u, v)
fig.add_traces(data = vec_field.data[0])
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(),
},
},
)
Однако сгенерированный график — это не то, что я ищу. В итоге карта перекрывает график колчана, поэтому я вообще не вижу стрелок. Есть ли какой-либо способ исправить это, чтобы стрелки были четко показаны над картой?
Ответ №1:
- использование стандартных трассировок и трассировок mapbox на одном рисунке проблематично
- если подумать со стороны, вы можете создать quiver из геометрии и использовать https://shapely.readthedocs.io/en/stable/manual.html#affine-transformations чтобы задать размер и направление вектора
import math
import geopandas as gpd
import pandas as pd
import plotly.express as px
import shapely.geometry
import numpy as np
from shapely.affinity import affine_transform as T
from shapely.affinity import rotate as R
# some geometry for an arrow
a = shapely.wkt.loads(
"POLYGON ((-0.6227064947841563 1.890841205238906, -0.3426264166591566 2.156169330238906, -0.07960493228415656 2.129731830238906, 1.952059130215843 0.022985736488906, -0.2085619635341561 -2.182924419761094, -0.6397611822841562 -1.872877544761094, -0.6636088385341563 -1.606053326011095, 0.5862935052158434 -0.400158794761094, -2.312440869784157 -0.3993228572610942, -2.526870557284156 -0.1848931697610945, -2.517313916659156 0.2315384708639062, -2.312440869784157 0.3990052677389059, 0.5862935052158434 0.399841205238906, -0.6363314947841564 1.565763080238906, -0.6227064947841563 1.890841205238906))"
)
gdf = (
gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
.set_crs("EPSG:4326")
)
# generate some data that has GPS co-ordinates, direction and magnitude of wind
df_wind = pd.concat(
[
pd.DataFrame(
{
"lat": np.linspace(*b[[0, 2]], 20),
"lon": np.linspace(*b[[1, 3]], 20),
"d": np.random.uniform(0, math.pi *2, 20),
"s": np.linspace(0.3, 1.5, 20),
}
)
for b in [gdf.sample(2)["geometry"].total_bounds for _ in range(5)]
]
).reset_index(drop=True)
# scatter points
t = (
px.scatter_mapbox(df_wind, lat="lon", lon="lat")
.update_layout(mapbox={"style": "carto-positron"})
.data
)
# wind direction and strength
px.choropleth_mapbox(
df_wind,
geojson=gpd.GeoSeries(
df_wind.loc[:, ["lat", "lon", "d", "s"]].apply(
lambda r: R(
T(a, [r["s"], 0, 0, r["s"], r["lat"], r["lon"]]),
r["d"],
origin=(r["lat"], r["lon"]),
use_radians=True,
),
axis=1,
)
).__geo_interface__,
locations=df_wind.index,
color="d",
).add_traces(t).update_layout(mapbox={"style": "carto-positron", "zoom": 1}, margin={"l":0,"r":0,"t":0,"b":0})