Цвет определенных ячеек из двух столбцов, которые не совпадают, используя Python Pandas style.where (или иным образом) и экспортировать в Excel

1

Я ищу цвет конкретных ячеек из двух столбцов, которые не совпадают, но хотел бы использовать его с python pandas style.where и экспортировать в excel с помощью openpyxl.

Мой код:

df = pd.DataFrame({
    'config_dummy1': ["dummytext"] * 100,
    'config_size_x': ["textstring"] * 100,
    'config_size_y': ["textstring"] * 100,
    'config_dummy2': ["dummytext"] * 100
})
df.at[50, 'config_size_x'] = "xandydontmatch"
df.at[99, 'config_size_y'] = "xandydontmatch"
print(df)
df.style.where(
    df['config_size_x'] != df['config_size_y'],
    'color: #ffffff; background-color: #ba3018',
    other=''
).to_excel('styled.xlsx', engine='openpyxl')

Я застреваю, так как он вызывает ошибку:

Traceback (most recent call last):
  File "python-match-csv.py", line 205, in <module>
    main2()
  File "python-match-csv.py", line 131, in main2
    ).to_excel('styled.xlsx', engine='openpyxl')
  File "F:\Python36\lib\site-packages\pandas\io\formats\style.py", line 175, in to_excel
    engine=engine)
  File "F:\Python36\lib\site-packages\pandas\io\formats\excel.py", line 652, in write
    freeze_panes=freeze_panes)
  File "F:\Python36\lib\site-packages\pandas\io\excel.py", line 1390, in write_cells
    for cell in cells:
  File "F:\Python36\lib\site-packages\pandas\io\formats\excel.py", line 617, in get_formatted_cells
    self._format_body()):
  File "F:\Python36\lib\site-packages\pandas\io\formats\excel.py", line 529, in _format_regular_rows
    for cell in self._generate_body(coloffset):
  File "F:\Python36\lib\site-packages\pandas\io\formats\excel.py", line 601, in _generate_body
    styles = self.styler._compute().ctx
  File "F:\Python36\lib\site-packages\pandas\io\formats\style.py", line 514, in _compute
    r = func(self)(*args, **kwargs)
  File "F:\Python36\lib\site-packages\pandas\io\formats\style.py", line 604, in _applymap
    result = self.data.loc[subset].applymap(func)
  File "F:\Python36\lib\site-packages\pandas\core\frame.py", line 6072, in applymap
    return self.apply(infer)
  File "F:\Python36\lib\site-packages\pandas\core\frame.py", line 6014, in apply
    return op.get_result()
  File "F:\Python36\lib\site-packages\pandas\core\apply.py", line 318, in get_result
    return super(FrameRowApply, self).get_result()
  File "F:\Python36\lib\site-packages\pandas\core\apply.py", line 142, in get_result
    return self.apply_standard()
  File "F:\Python36\lib\site-packages\pandas\core\apply.py", line 248, in apply_standard
    self.apply_series_generator()
  File "F:\Python36\lib\site-packages\pandas\core\apply.py", line 277, in apply_series_generator
    results[i] = self.f(v)
  File "F:\Python36\lib\site-packages\pandas\core\frame.py", line 6070, in infer
    return lib.map_infer(x.astype(object).values, func)
  File "pandas/_libs/src\inference.pyx", line 1472, in pandas._libs.lib.map_infer
  File "F:\Python36\lib\site-packages\pandas\io\formats\style.py", line 671, in <lambda>
    return self.applymap(lambda val: value if cond(val) else other,
TypeError: ("'Series' object is not callable", 'occurred at index config_dummy1')

TypeError: ("Объект" Series "не может быть вызван", "произошел в index config_dummy1"

Я открыт для предложений, отличных от.where(). Я также пытался сделать это с помощью.apply(), но не смог.

Примечание: позиция индекса столбца не является фиксированной, это могут быть config_size_x, config_dummy1, config_dummy2, config_size_y или любая другая комбинация

Примечание 2: использование окон и python 3.6, если это имеет значение

  • 0
    the column index position is not fixed, it could be config_size_x, config_dummy1, config_dummy2, config_size_y or any other combination - так что нужно сравнить config_dummy1 с config_dummy2 и аналогичными для каждой пары? DataFrame всегда содержит пары столбцов?
  • 0
    DataFrame содержит много (около 50-60 столбцов) config_COLNAME_y и config_COLNAME_x, которые каждый раз не находятся в одной и той же позиции индекса. config_size_x и config_size_y являются одними из них, но если я правильно понял, я могу оттуда построить свой путь. Да, они всегда в парах _x и _y
Теги:
pandas
dataframe
excel
styleframe

2 ответа

1
Лучший ответ

Вы можете создать DataFrame стилей с apply:

def color(x):
    c1 = 'color: #ffffff; background-color: #ba3018'
    m = x['config_size_x'] != x['config_size_y']
    df1 = pd.DataFrame('', index=x.index, columns=x.columns)
    df1.loc[m, ['config_size_x', 'config_size_y']] = c1
    return df1

df.style.apply(color, axis=None)

Общее решение:

df = pd.DataFrame({
    'config_dummy1': ["dummytext"] * 10,
    'a_y': ["a"] * 10,
    'config_size_x': ["textstring"] * 10,
    'config_size_y': ["textstring"] * 10,
    'config_dummy2': ["dummytext"] * 10,
    'a_x': ["a"] * 10
})
df.at[5, 'config_size_x'] = "xandydontmatch"
df.at[9, 'config_size_y'] = "xandydontmatch"
df.at[0, 'a_x'] = "xandydontmatch"
df.at[3, 'a_y'] = "xandydontmatch"
print(df)

def color(x):
    c1 = 'color: #ffffff; background-color: #ba3018'
    df1 = pd.DataFrame('', index=x.index, columns=x.columns)

    #select only columns ends with _x and _y and sorting
    cols = sorted(x.filter(regex='_x$|_y$').columns)
    #loop by pairs and assign style by mask
    for i, j in zip(cols[::2],cols[1::2]):
        #pairs columns 
        #print (i, j)
        m = x[i] != x[j]
        df1.loc[m, [i, j]] = c1
    return df1

df.style.apply(color, axis=None).to_excel('styled.xlsx', engine='openpyxl')
  • 0
    Спасибо за ваш быстрый ответ, и я вижу подход apply (), но, к сожалению, он окрашивает весь ряд. Есть ли способ закрасить только определенные ячейки config_size_x и config_size_y?
  • 1
    @SavvasRadevic - да, конечно, проверьте отредактированный ответ.
Показать ещё 4 комментария
2

Поскольку этот вопрос отмечен styleframe:

from StyleFrame import StyleFrame, Styler

df = pd.DataFrame({'a': [1, 2], 'b': [1, 3]})

sf = StyleFrame(df)
sf.apply_style_by_indexes(sf[sf['a'] != sf['b']], styler_obj=Styler(bg_color='red'))
sf.to_excel('test.xlsx').save()

Будет производить

Изображение 174551

Если вы хотите покрасить только подмножество несоответствующих строк, вы можете просто использовать cols_to_style param:

sf.apply_style_by_indexes(sf[sf['a'] != sf['b']], styler_obj=Styler(bg_color='red'),
                          cols_to_style=['a', 'b'])

Изображение 174551

  • 0
    Я открыт для любого обходного решения :) Я забыл упомянуть, что я также пробовал стиль рамки и не смог закрасить определенные ячейки. : D К сожалению, ваш ответ раскрашивает весь ряд. Есть ли способ закрасить только определенные ячейки config_size_x и config_size_y?
  • 1
    @SavvasRadevic Да, довольно легко. Смотрите мой обновленный ответ
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню