Использование pd.xlsxwriter для условного форматирования всей строки на основе одной ячейки в этой строке

#python #pandas #xlsxwriter

Вопрос:

У меня есть следующий код:

 import pandas as pd from datetime import datetime  writer = pd.ExcelWriter(  f"~/{datetime.today().strftime('%Y.%m.%d')} - Report.xlsx",  engine="xlsxwriter",  date_format="dd/mm/yyyy",  datetime_format="dd/mm/yyyy",  ) worksheet = writer.sheets["Sheet1"] comma_format = workbook.add_format(  {"num_format": "#,###;[Red](#,###);-", "bold": True}  ) worksheet.conditional_format(  "$A$2:$J$1000",  {  "type": "cell",  "criteria": "containing",  "value": '"Total"',  "format": comma_format,  },  )  

Я хотел бы, чтобы всякий раз, когда строка содержит слово «Всего» в любой ячейке строки, форматировать всю ячейку с comma_format помощью .

Однако приведенный выше сценарий форматирует только ячейку, содержащую «Всего», а не всю строку.

Есть какие-нибудь идеи о том, как я могу это исправить?

Большое спасибо,

Майк

Комментарии:

1. В общем, вам нужно сначала выяснить, как выполнить сложный условный формат в Excel, а затем перенести его в XlsxWriter. Сказав это, я не думаю, что то, что вы хотите сделать, возможно с помощью одного условного формата. Подход, который вы обычно используете, заключается в использовании условного формата формулы с абсолютной привязкой в строке. Однако этот якорь может находиться только в одном столбце в строке. Таким образом, вам нужно будет воспроизвести условный формат для каждого столбца в строке. Насколько я знаю, это скорее вопрос Excel, чем вопрос на Python.

Ответ №1:

Вы можете использовать операции с кадрами данных для получения индексов строк, содержащих слово Total, например. rows_with_total = df[df.applymap(lambda x: True if isinstance(x, str) and 'total' in x.lower() else False).any(1)].index.to_list() .

applymap выполняет итерацию по всем значениям во фрейме данных и применяет переданную функцию к каждому из них. В этом случае он возвращает True , если значение является строкой и содержит слово total, в противном случае он возвращается False .

any Метод с переданным 1 проверяет, есть ли какое-либо значение в строке True , и возвращает значение a Series booleans ( True если есть какой-либо столбец в строке True и False в противном случае). Перенос этой части в df [«эта часть»] фильтрует строки, которые возвращаются, на основе Series boolean значений.

Затем .index.to_list() возвращает индексы отфильтрованных строк в виде a list .

С помощью этого списка вы можете затем сделать то, что предложил @drew_wood, и перебирать строки, применяя формат к каждой из них таким образом.

 for row in rows_with_total:  worksheet.set_row(row, None, comma_format)  

Полный код

 rows_with_total = df[df.applymap(lambda x: True if isinstance(x, str) and 'total' in x.lower() else False).any(1)].index.to_list() for row in rows_with_total:  worksheet.set_row(row, None, comma_format)  

Ответ №2:

Вы можете сохранить каждую строку в своем фрейме данных в виде списка, используя df.values

Затем вы можете просмотреть этот список, проверив, чтобы увидеть if 'Total' in list:

Если это так, вы можете затем просмотреть каждый столбец в этой строке и присвоить (row_ind,col_ind) желаемый формат.