Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotly Express timeline for Gantt Chart with integer xaxis?

I'm using plotly express timeline to produce a Gantt chart following this example: https://medium.com/dev-genius/gantt-charts-in-python-with-plotly-e7213f932f1e

It automatically sets the x-axis to use dates but I'd actually like to just use integers (i.e. Project Kick-Off +1, Project Kick-Off +6, etc).

Is there a way to make a timeline plot NOT use dates for the xaxis?

If I try using integers it'll treat them like milliseconds.

like image 817
Rob Avatar asked Dec 14 '22 07:12

Rob


2 Answers

The answer:

Yes, it's possible! Just give integers as start and end "dates", calculate the difference between them (delta), and make these changes to your fig:

fig.layout.xaxis.type = 'linear'
fig.data[0].x = df.delta.tolist()

Plot

enter image description here

The details:

There actually is a way to achieve this, although the docs state that:

The px.timeline function by default sets the X-axis to be of type=date, so it can be configured like any time-series chart.

And therefore every other functionality in px.timeline() seems to revolve around that fact. But if you just ignore that and use integers as values for Start and Finish, then you can tweak a few attributes to get what you want. You just need to calculate the differences between each Start and Stop. For example like this:

df = pd.DataFrame([
    dict(Task="Job A", Start=1, Finish=4),
    dict(Task="Job B", Start=2, Finish=6),
    dict(Task="Job C", Start=3, Finish=10)
])
df['delta'] = df['Finish'] - df['Start']

And then tweak a little further:

fig.layout.xaxis.type = 'linear'
fig.data[0].x = df.delta.tolist()

Complete code:

import plotly.express as px
import pandas as pd

df = pd.DataFrame([
    dict(Task="Job A", Start=1, Finish=4),
    dict(Task="Job B", Start=2, Finish=6),
    dict(Task="Job C", Start=3, Finish=10)
])
df['delta'] = df['Finish'] - df['Start']

fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task")
fig.update_yaxes(autorange="reversed") 

fig.layout.xaxis.type = 'linear'
fig.data[0].x = df.delta.tolist()
f = fig.full_figure_for_development(warn=False)
fig.show()
like image 135
vestland Avatar answered Jan 03 '23 10:01

vestland


I think this is much simpler solution than above when we have to specify color

for d in fig.data:
  filt = df['color'] == d.name
  d.x = df[filt]['Delta'].tolist()
like image 39
JounghooLee Avatar answered Jan 03 '23 09:01

JounghooLee