Стиль фрейма данных Pandas: выделите некоторые ячейки на основе столбца формата

#python #pandas #dataframe

#python #панды #фрейм данных

Вопрос:

Описание проблемы

У меня есть фрейм данных, в котором последний столбец является столбцом формата. Цель этого столбца — содержать формат строки фрейма данных. Вот пример такого фрейма данных:

 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']}
  

Каждая строка df[‘format’] содержит строку, предназначенную для использования в качестве списка (при разделении), чтобы задать формат строки.

Значение символов:

  • n означает «нет выделения»
  • y означает «выделить желтым цветом»

df[‘format’].to_list()[0] = ‘n;y;n’ означает, например:

  • n: элемент идентификатора первого столбца «1» не выделен
  • y: второй элемент состояния столбца «для анализа», который будет выделен
  • n: элемент приоритета третьего столбца «P1» не выделен

Таким образом, ожидаемый результат:

Ожидаемый результат

Что я пробовал

Я попытался использовать df.format, чтобы получить список списков, содержащих необходимый формат. Вот мой код:

 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)
  

Это не работает, и я получаю этот вывод:

 TypeError                                 Traceback (most recent call last)
c:python38libsite-packagesIPythoncoreformatters.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:python38libsite-packagespandasioformatsstyle.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:python38libsite-packagespandasioformatsstyle.py in render(self, **kwargs)
    538         * table_attributes
    539         """
--> 540         self._compute()
    541         # TODO: namespace all the pandas keys
    542         d = self._translate()

c:python38libsite-packagespandasioformatsstyle.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:python38libsite-packagespandasioformatsstyle.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:python38libsite-packagespandascoreframe.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:python38libsite-packagespandascoreapply.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:python38libsite-packagespandascoreframe.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:python38libsite-packagespandascoreaggregation.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:

Поскольку форматы кодируются для каждой строки, это имеет смысл по apply строкам:

 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)
  

Вывод:

введите описание изображения здесь