Why is the .apply function for the .style attribute in Panel.Tabulator/pandas.DataFrame not called/accessed?

I have a funtion in my project, using pandas and Panel, which has a strange behaviour.

    def _filter_cluster_df(self, selected_items):
        def _highlight(row, mask_i):
            print("inside")
            return ['font-weight: bold;']*len(row) if mask_i else ['']*len(row)
        if not isinstance(selected_items, list):
            slogans= selected_items['items'].explode().unique()
            slogans_first_part = np.array([s.split('_')[0].strip() for s in slogans])
        else:
            slogans= list(set([s for sublist in selected_items for s in sublist]))
            slogans_first_part= [s.split('_')[0].strip() for s in slogans]
        mask= self.table.df['list_slogans'].isin(slogans_first_part)
        print("before")
        self.table.table.style.apply(lambda r: _highlight(r, mask.iloc[r.name]), axis=1)
        print("after")
        return

self.table is an object which has an attribute called table that is a Panel.Tabulator. The Tabulator widget exposes a .style attribute just like a pandas.DataFrame which lets the user apply custom styling using methods like .apply. The behavior I would like to achieve is that, every time the function is called, its style is updated and the change is visible on the table.

I added the print for debugging purpose and I noticed the following actions:

  • when the function is called for the first time (when the table is created), it seems to work well (the layout appears with the applied style), but the several inside (one for each row) are printed after the before and the after (as if something were behaving asynchronously).
  • from the second call of _filter_cluster_df (it is a function also called by clicking on certain buttons), only the before and the after are printed (not the sequence inside) and the layout of the table remains unchanged (even if the mask changes) (the _highlight is not accessed).

I am sure that the code which creates the mask works well.

It may not directly fix your problem, but I noticed that tach time you call style.apply it appends an additional function to the stack that is called when the table is re-rendered. You should probably only call style.apply once for the whole table.

Thanks for the answer, but I discovered that the apply function is ‘triggered’ only when the current_view of the table changes (therefore changing the order of the df or inserting filters), which is why I didn’t see the changes nor the prints of ‘inside’.

def _filter_cluster_df(self, selected_items):
        def _highlight(row, mask_i):
            print("inside")
            return ['font-weight: bold;']*len(row) if mask_i else ['']*len(row)
        if not isinstance(selected_items, list):
            slogans= selected_items['items'].explode().unique()
            slogans_first_part = np.array([s.split('_')[0].strip() for s in slogans])
        else:
            slogans= list(set([s for sublist in selected_items for s in sublist]))
            slogans_first_part= [s.split('_')[0].strip() for s in slogans]
        mask= self.table.df['list_slogans'].isin(slogans_first_part)
        print("before")
        self.table.table.style.apply(lambda r: _highlight(r, mask.iloc[r.name]), axis=1)
        print("after")
        # It is necessary to modify the current_view of the table, here changing its 'list_slogans' sorting, to 'trigger' the style changes
        self.direction= 'desc' if self.direction=='asc' else 'asc'
        self.table.table.sorters= [{'field': 'list_slogans', 'dir': self.direction}]
        return