Black Lives Matter. Please consider donating to Black Girls Code today.

Filter in create_gantt

Dear all,
I am trying to figure out how to set a filter for a fourth column I am using. It works fine if I use the “normal” way to generate a figure but if I am using the Figure Factory and create_gantt the transformation does not get applied. Here is my code:

df = []
source = []
for row in cursor:
   df.append(dict(Task=row[0], Start=row[1] , Finish=row[2], Source=row[4],Description=row[3]))
   source.append(row[3])
   
colors = {'70': 'rgb(220, 0, 0)',
          '90': 'rgb(50, 168,82)',
          '30': 'rgb(252, 165, 3)',
          '80': 'rgb(0, 0, 0)',
          '00': 'rgb(102, 0, 255)'
         }
#df.append()
fig = ff.create_gantt(df,colors=colors, showgrid_x=True, showgrid_y=True, index_col="Source", show_colorbar=True, group_tasks=True, bar_width=0.4, height=900, 
data=[dict(transforms =[dict(
      meta=source,
      transforms = [dict(
         type = "filter", 
         target = "Description", 
         operation = "=", 
         value = None
      )
      ]
)])
    ]) 

fig.update_layout(
   updatemenus=[
        dict(
            buttons=list([
               dict(
                    args=[{"transforms[0].enabled": False}],
                    label="All",
                    method="restyle"
                ),
                dict(
                    args=[{"transforms[0].value": "Value1"}],
                    label="Value1",
                    method="restyle"
                ),
                dict(
                    args=[{"transforms[0].value": "Value2"}],
                    label="Value2",
                    method="restyle"
                ), 
                dict(
                    args=[{"transforms[0].value": "Value3"}],
                    label="Value3",
                    method="restyle"
                ),                   
            ]),
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.1,
            xanchor="left",
            y=1.1,
            yanchor="top"
        ),
    ]
)
fig.update_xaxes(tickson="labels")
fig.show()

The “Description” field contains the values that I want to filter.

Another question: How can I disable the filter for one dropdown (in this example for “All”) but activate it for the others?

Anyone? I would really like to get this solved.

Hi, i’m not being able to reproduce your example.

Hi!
Thank you for your answer!
Do you mind telling/showing me how you filter with create_gantt?

Hi @jkoch,

Applying a filter to a fig returned by ff.create_gantt() isn’t straightforward.
First of all no graph_objects has a property transforms (for example, typing help(go.Scatter.transforms)
you’ll get:

AttributeError                            Traceback (most recent call last)
<ipython-input-19-c39b71b175ce> in <module>
----> 1 help(go.Scatter.transforms)

AttributeError: type object 'Scatter' has no attribute 'transforms'

There is an old proposal for enhancement, here https://github.com/plotly/plotly.py/issues/587, but it isn’t implemented.

However there is a workaround:

  • define your fig=ff.create_gantt() with no transform;
  • since fig is an instance of go.Figure, i.e. a graph_objects, convert it to a dict:
my_fig = fig.to_dict()
  • inspect the traces from my_fig['data'] and if you want to insert a transform in my_fig['data'][1] perform it, like this:
my_fig['data'][1]['transforms'] = [dict(
                                      type = 'filter',
                                      target = 'y',
                                      operation = '>',
                                      value = 4
                                    )]
  • when all transforms have been defined, you cannot use my_fig.show() to display the corresponding figure because my_fig isn’t an instance of the class go.Figure,
    and you cannot convert it back , because transforms is not a property for graph_objects
    A workaround is to import plotly.io:
import plotly.io as pio
pio.show(my_fig, validate=False)

Now let us take a simple Gantt chart and perform the above operations on it:

import plotly.figure_factory as ff
df = [dict(Task="Job 1", Start='2009-01-01', Finish='2009-02-28', Description='A'),
      dict(Task="Job 2", Start='2008-12-05', Finish='2009-04-15', Description='B'),
      dict(Task="Job 3", Start='2009-02-20', Finish='2009-05-30', Description='A')]

fig = ff.create_gantt(df, colors='Viridis', index_col='Description', show_colorbar=False)
fig.show()

Convert fig to a dict:

my_fig = fig.to_dict()
# if working in a Jupyter Notebook type `my_fig` in a new code cell, and run it to inspect the resulting dict
print(len(my_fig['data'])
4

Hence my_fig['data'] contains 4 traces:

my_fig['data'][0]#  defines the horizontal bar as a filled scatter trace for the job with 'B' as description

{'fill': 'toself',
 'fillcolor': 'rgb(253, 231, 37)',
 'hoverinfo': 'name',
 'legendgroup': 'rgb(253, 231, 37)',
 'mode': 'none',
 'name': 'B',
 'showlegend': False,
 'x': ['2008-12-05', '2009-04-15', '2009-04-15', '2008-12-05'],
 'y': [0.8, 0.8, 1.2, 1.2],
 'type': 'scatter'}
 
my_fig['data'][1]#  defines the horizontal bar as a filled scatter trace for the the two jobs with 'A' as description 

{'fill': 'toself',
 'fillcolor': 'rgb(68, 1, 84)',
 'hoverinfo': 'name',
 'legendgroup': 'rgb(68, 1, 84)',
 'mode': 'none',
 'name': 'A',
 'showlegend': False,
 'x': ['2009-01-01',
  '2009-02-28',
  '2009-02-28',
  '2009-01-01',
  '2009-01-01',
  '2009-02-20',
  '2009-05-30',
  '2009-05-30',
  '2009-02-20'],
 'y': [-0.2, -0.2, 0.2, 0.2, None, 1.8, 1.8, 2.2, 2.2],
 'type': 'scatter'}

The next two traces associate the explanatory strings to be displayed as text at the two ends of each horizontal bar. Now you can insert the desired transforms into a trace, at your convenience.

And finally, this link could be an inspiration to define your updatemenus
https://codepen.io/etpinard/pen/dpKLpq.