Reputation: 2143
I don't know if the title describes my problem, but that's my best guess.
creating a gannt plot in plotly is easy enough (https://plotly.com/python/gantt/).
Additionally, I want to indicate certain critical events. As those are non-specific to categories,
I don't want them to refer to a certain category on the y-axis. So I want to go with vertical lines. That is still easy enough (add_vline
). But those lines also need to labeled with the event name, the events usually have very long names. That can be done by annotating the vertical lines. As the event names are very long, I thought that offsetting them in y-direction would be a good idea.
The end-result should look like this:
Labeling the vertical lines works well for roughly the first three events, but then the annotations get out of the canvas(?) allocated for the graph. I tried to indicate this with the black dashed frame.
Consequently, the texts "text that gets cut off" and "no chance" are not displayed. How can I fix this? I read that the annotations are not really graph objects but and as such, the dimensions of the graph are not expanded to the annotations' coordinates. But I also found no "text graph objects" in plotly.
Upvotes: 2
Views: 2751
Reputation: 61094
You should be able to get what you want through a combination of shapes
, annotations
, and a correct adjustment of margins
. The setup below does just that, and annotates the shapes with an increasingly negative offset to the zero line using y = -0.2-(i/10)
and yref = 'paper'
in fig.add_annotation()
. As it now stands, the approach isn't very dynamic with regards to number of annotated lines, but we can take a closer look at that if this figure does in fact represent the essence of what you're looking for:
import plotly.express as px
import pandas as pd
df = pd.DataFrame([
dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28'),
dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15'),
dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30')
])
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task")
fig.update_yaxes(autorange="reversed")
events = [{'date':'2009-02-01', 'annotation': 'some important information', 'color':'red'},
{'date':'2009-04-01', 'annotation': 'some very important stuff', 'color':'green'}]
for i, e in enumerate(events):
fig.add_shape(type = 'line', x0 = e['date'], x1 = e['date'], y0 = 0, y1 = 1, yref = 'paper',
line = dict(color = e['color']))
fig.add_annotation(x = e['date'], y = -0.2-(i/10), text = e['annotation'],
yref = 'paper', showarrow = False,
font=dict(color=e['color'],size=12))
fig.update_layout(margin=dict(l=25,
r=25,
b=100,
t=25,
pad=4),
paper_bgcolor="LightSteelBlue")
fig.show()
Upvotes: 2