6

Problem description

I have a DataFrame in which last column is a format column. The purpose of this column is to contain the format of the DataFrame row. Here is an example of such a dataframe:

df = pd.DataFrame({'ID': [1, 24, 31, 37],
                   'Status': ['to analyze', 'to analyze','to analyze','analyzed'],
                   'priority' : ['P1','P1','P2','P1'],
                   'format' : ['n;y;n','n;n;n','n;y;y','y;n;y']}

Each df['format'] row contains a string intended to be taken as a list (when split) to give the format of the row.

Symbols meaning:

  • n means "no highlight"
  • y means "to highlight in yellow"

df['format'].to_list()[0] = 'n;y;n' means for example:

  • n: first column ID item "1" not highlighted
  • y: second column Status item "to analyze" to be highlighted
  • n: third column Priority item "P1" not highlighted

So that expected outcome is:

Expected outcome

What I've tried

I've tried to use df.format to get a list of lists containing the format needed. Here is my code:

import pandas as pd
import numpy as np

def highlight_case(df):
    list_of_format_lists = []
    for format_line in df['format']:
        format_line_list = format_line.split(';')
        format_list = []
        for form in format_line_list:
            if 'y' in form:
                format_list.append('background-color: yellow')
            else:
                format_list.append('')
        list_of_format_lists.append(format_list)
    list_of_format_lists = list(map(list, zip(*list_of_format_lists)))#transpose
    print(list_of_format_lists)
    return list_of_format_lists


highlight_style = highlight_case(df)
df.style.apply(highlight_style)

It doesn't work, and I get this output:

TypeError                                 Traceback (most recent call last)
c:\python38\lib\site-packages\IPython\core\formatters.py in __call__(self, obj)
    343             method = get_real_method(obj, self.print_method)
    344             if method is not None:
--> 345                 return method()
    346             return None
    347         else:

c:\python38\lib\site-packages\pandas\io\formats\style.py in _repr_html_(self)
    191         Hooks into Jupyter notebook rich display system.
    192         """
--> 193         return self.render()
    194 
    195     @doc(NDFrame.to_excel, klass="Styler")

c:\python38\lib\site-packages\pandas\io\formats\style.py in render(self, **kwargs)
    538         * table_attributes
    539         """
--> 540         self._compute()
    541         # TODO: namespace all the pandas keys
    542         d = self._translate()

c:\python38\lib\site-packages\pandas\io\formats\style.py in _compute(self)
    623         r = self
    624         for func, args, kwargs in self._todo:
--> 625             r = func(self)(*args, **kwargs)
    626         return r
    627 

c:\python38\lib\site-packages\pandas\io\formats\style.py in _apply(self, func, axis, subset, **kwargs)
    637         data = self.data.loc[subset]
    638         if axis is not None:
--> 639             result = data.apply(func, axis=axis, result_type="expand", **kwargs)
    640             result.columns = data.columns
    641         else:

c:\python38\lib\site-packages\pandas\core\frame.py in apply(self, func, axis, raw, result_type, args, **kwds)
   7543             kwds=kwds,
   7544         )
-> 7545         return op.get_result()
   7546 
   7547     def applymap(self, func) -> "DataFrame":

c:\python38\lib\site-packages\pandas\core\apply.py in get_result(self)
    142         # dispatch to agg
    143         if is_list_like(self.f) or is_dict_like(self.f):
--> 144             return self.obj.aggregate(self.f, axis=self.axis, *self.args, **self.kwds)
    145 
    146         # all empty

c:\python38\lib\site-packages\pandas\core\frame.py in aggregate(self, func, axis, *args, **kwargs)
   7353         axis = self._get_axis_number(axis)
   7354 
-> 7355         relabeling, func, columns, order = reconstruct_func(func, **kwargs)
   7356 
   7357         result = None

c:\python38\lib\site-packages\pandas\core\aggregation.py in reconstruct_func(func, **kwargs)
     74 
     75     if not relabeling:
---> 76         if isinstance(func, list) and len(func) > len(set(func)):
     77 
     78             # GH 28426 will raise error if duplicated function names are used and

TypeError: unhashable type: 'list'

1 Answer 1

2

Since the formats are encoded for each row, it makes sense apply row-wise:

def format_row(r):
    formats = r['format'].split(';')
    return ['background-color: yellow' if y=='y' else '' for y in formats] + ['']

df.style.apply(format_row, axis=1)

Output:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.