'In Python, how can I update plotly figures using 'update_annotations'?

I am using Plotly in python to generate figures. As in the title, I cannot update figure annotations with the update_annotations function.

The following is an example of multiplot.

data = pd.DataFrame(np.random.rand(10,3), columns=['A', 'B', 'C'], index=pd.date_range(start='2001-01-01', periods=10))

fig = make_subplots(rows=3, cols=1, subplot_titles=['Top','Middle', 'Bottom'])

fig.add_trace(go.Scatter(x=data.index, y=data['A'], mode='lines'), row=1, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data['B'], mode='lines'), row=2, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data['C'], mode='lines'), row=3, col=1)

I can change the name of the top figure from 'TOP' to 'TOP_TEST' and its position with the following code.

fig['layout']['annotations'][0]['text'] = 'TOP_TEST'
fig['layout']['annotations'][0]['x'] = 0.02

However, I do not understand why I cannot do the same with the function update_annotations. If it works, it seems to be much easier to change multiple parameters at once.

fig.update_annotations(row=1, col=1, text='TOP_TEST', x=0.02)

Thank you for any comment in advance.



Solution 1:[1]

  • have looked into plotly code. update_annotations() uses _select_annotations_like()
  • whenever you specify row or col parameters the internal method returns effectively an empty list. Code gets a bit more challenging to follow after that. This appears to be a bug
  • as a work around you can use update_annotations() with selector parameter. Demonstrated in code below
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.express as px


data = pd.DataFrame(np.random.rand(10,3), columns=['A', 'B', 'C'], index=pd.date_range(start='2001-01-01', periods=10))

fig = make_subplots(rows=3, cols=1, subplot_titles=['Top','Middle', 'Bottom'])

fig.add_trace(go.Scatter(x=data.index, y=data['A'], mode='lines'), row=1, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data['B'], mode='lines'), row=2, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data['C'], mode='lines'), row=3, col=1)

# empty so nothing to update...
list(fig._select_annotations_like(prop="annotations", row=1, col=1))

# select based on text on we're ok
fig.update_annotations(selector={"text":"Top"}, text="TOP_TEST", x=.02)


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rob Raymond