Plotly Express: trying to add button to re-draw Gantt chart/timeline

Viewed 36

I'm trying to produce a Gantt-type timeline chart with additional controls (buttons, etc) to re-draw the chart based on different formatting needs. I'm working from the basic example shown in the Plotly documentation: https://plotly.com/python/gantt/

I'm trying to add a button that would allow for re-grouping events by task, or by resource (or other categorical variables). The following code is my first attempt. It does allow me to re-draw the figure once, but subsequent clicks doesn't switch the format back:

import plotly.express as px
import pandas as pd

df = pd.DataFrame([
    dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28', Resource="Alex"),
    dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15', Resource="Alex"),
    dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30', Resource="Max")
])

fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource")

fig.update_layout(
    updatemenus=[
        dict(
            type = "buttons",
            direction = "left",
            buttons=list([
                dict(
                    args=[{"y" : "Resource"}],
                    label="By Resource",
                    method="restyle"
                ),
                dict(
                    args=[{"y": "Task"}],
                    label="By Task",
                    method="restyle"
                )
            ]),
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.11,
            xanchor="left",
            y=1.1,
            yanchor="top"
        ),
    ]
)

fig.show()

Am I misconfiguring the button/not using the update_layout and updatemenus methods correctly?

1 Answers

I don't think plotly.express allows switching with the custom button, so in this case I would use the data created in plotly.express to draw the graph. Display the initial graph with the task criteria and hide the resource criteria. Set the buttons to show/hide in the list according to each button. As an adjustment to the graph, the x-axis is set to date type and the y-axis is set to reverse order.

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

df = pd.DataFrame([
    dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28', Resource="Alex"),
    dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15', Resource="Alex"),
    dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30', Resource="Max")
])

task = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource")
resource = px.timeline(df, x_start="Start", x_end="Finish", y="Resource", color="Resource")

fig = go.Figure()
fig.add_trace(go.Bar(task.data[0], visible=True))
fig.add_trace(go.Bar(task.data[1], visible=True))
fig.add_trace(go.Bar(resource.data[0], visible=False))
fig.add_trace(go.Bar(resource.data[1], visible=False))

fig.update_xaxes(type='date')
fig.update_yaxes(autorange="reversed")

fig.update_layout(
    updatemenus=[
        dict(
            type = "buttons",
            direction = "left",
            buttons=list([
                dict(
                    args=[{"visible": [True, True, False, False]}],
                    label="By Task",
                    method="update"
                ),                dict(
                    args=[{"visible" : [False, False, True, True]}],
                    label="By Resource",
                    method="update"
                ),
            ]),
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.01,
            xanchor="left",
            y=1.30,
            yanchor="top"
        ),
    ]
)

fig.show()

enter image description here

enter image description here

Related