Writing pandas DataFrame to Excel with different formats for different columns
Solution 1
You can do this with Pandas 0.16 and the XlsxWriter engine by accessing the underlying workbook and worksheet objects:
import pandas as pd
# Create a Pandas dataframe from some data.
df = pd.DataFrame(zip(
[1010, 2020, 3030, 2020, 1515, 3030, 4545],
[.1, .2, .33, .25, .5, .75, .45],
[.1, .2, .33, .25, .5, .75, .45],
))
# Create a Pandas Excel writer using XlsxWriter as the engine.
writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1')
# Get the xlsxwriter objects from the dataframe writer object.
workbook = writer.book
worksheet = writer.sheets['Sheet1']
# Add some cell formats.
format1 = workbook.add_format({'num_format': '#,##0.00'})
format2 = workbook.add_format({'num_format': '0%'})
format3 = workbook.add_format({'num_format': 'h:mm:ss AM/PM'})
# Set the column width and format.
worksheet.set_column('B:B', 18, format1)
# Set the format but not the column width.
worksheet.set_column('C:C', None, format2)
worksheet.set_column('D:D', 16, format3)
# Close the Pandas Excel writer and output the Excel file.
writer.save()
Output:
See also Working with Python Pandas and XlsxWriter.
Solution 2
As you rightly point out applying formats to individual cells is extremely inefficient.
openpyxl 2.4 includes native support for Pandas Dataframes and named styles.
https://openpyxl.readthedocs.io/en/latest/changes.html#id7
sparc_spread
Some days I'm a data scientist. Some days I'm a software engineer. Every day I'm a dad.
Updated on July 09, 2022Comments
-
sparc_spread almost 2 years
I am trying to write a pandas
DataFrame
to an.xlsx
file where different numerical columns would have different formats. For example, some would show only two decimal places, some would show none, some would be formatted as percents with a "%" symbol, etc.I noticed that
DataFrame.to_html()
has aformatters
parameter that allows one to do just that, mapping different formats to different columns. However, there is no similar parameter on theDataFrame.to_excel()
method. The most we have is afloat_format
that is global to all numbers.I have read many SO posts that are at least partly related to my question, for example:
-
Use the older
openpyxl
engine to apply formats one cell at a time. This is the approach with which I've had the most success. But it means writing loops to apply formats cell-by-cell, remembering offsets, etc. -
Render percentages by changing the table data itself into strings. Going the route of altering the actual data inspired me to try dealing with decimal place formatting by calling
round()
on each column before writing to Excel - this works too, but I'd like to avoid altering the data. - Assorted others, mostly about date formats
Are there other more convenient Excel-related functions/properties in the pandas API that can help here, or something similar on
openpyxl
, or perhaps some way to specify output format metadata directly onto each column in theDataFrame
that would then be interpreted downstream by different outputters? -
Use the older