Search code examples
pythonplotlyplotly-python

Rotate Plotly Scatter Markers to create Wind Arrows on a Timeseries Plot


Trying to create a plot displaying the wind conditions with arrows visualizing the direction of the wind at a certain timestamp. Target Visualization

The above visualization could be created by converting the datetime index and fixing the scale-ratio.

With plotly 5.13.0 markers haven gotten the angle property (Plotly Reference), which motivated me to give it an other go using a native datetime index and scatter-markers.

The angle property can only be set once per trace as it seems, thus we'll need to loop.

Sample Data Generation

import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go

np.random.seed(seed=13)

idx = pd.date_range("2023-07-11 10:05", "2023-07-11 11:00", freq='5min')
wind_speeds = np.random.random_sample(size=len(idx)) * 3
wind_directions = np.random.randint(0, high=3600, size=len(idx)) / 10.0
df = pd.DataFrame({'datetime': idx, 'V_WIND': wind_speeds, 'DIR_WIND': wind_directions})
df['datetime'] = pd.to_datetime(df.datetime)
df = df.set_index('datetime')
datetime V_WIND DIR_WIND
2023-07-11 10:05:00 2.333107 323.2
2023-07-11 10:10:00 0.712624 296.3
2023-07-11 10:15:00 2.472836 219.7
2023-07-11 10:20:00 2.897248 142.7

Current Attempt

def plot_wind(df: pd.DataFrame) -> None:
    fig = px.line(df, y="V_WIND")
    for wind_row in df.iterrows():
        fig.add_trace(
            go.Scatter(
                x=[wind_row[0]],
                y=[wind_row[1]['V_WIND']],
                showlegend=False,
                marker=dict(
                    color='red',
                    size=20,
                    symbol='triangle-down-open',
                    angle=[wind_row[1]['DIR_WIND']],
                )))
    fig.show()


plot_wind(df)

Output Figure without rotated Markers The angle property has no effect at all. Even when fixing it to a value such as 25.0, the markers look identical. How can we get them to rotate?


Solution

  • As mentioned by @r-beginners in the comments, updating to Plotly 5.15.0 should fix the issue.

    I just wanted to add that you can add the markers to the trace (with mode='lines+markers') instead of adding one trace for each :

    fig = go.Figure(go.Scatter(
        x=df.index,
        y=df['V_WIND'],
        mode='lines+markers',
        line=dict(color='blue'),
        marker=dict(
            color='red',
            size=20,
            symbol='triangle-down-open',
            angle=df['DIR_WIND']
        )
    ))
    

    Or

    fig = px.line(df, y="V_WIND")
    
    fig.update_traces(dict(
        mode='lines+markers',
        marker=dict(
            color='red',
            size=20,
            symbol='triangle-down-open',
            angle=df['DIR_WIND']
        )
    ))
    

    enter image description here