Writing Percentages in Excel Using Pandas

Question:

When writing to csv’s before using Pandas, I would often use the following format for percentages:

'%0.2f%%' % (x * 100)

This would be processed by Excel correctly when loading the csv.

Now, I’m trying to use Pandas’ to_excel function and using

(simulated * 100.).to_excel(writer, 'Simulated', float_format='%0.2f%%')

and getting a “ValueError: invalid literal for float(): 0.0126%”. Without the ‘%%’ it writes fine but is not formatted as percent.

Is there a way to write percentages in Pandas’ to_excel?

This question is all pretty old at this point. For better solutions check out xlsxwriter working with pandas.

Asked By: rhaskett

||

Answers:

You can do the following workaround in order to accomplish this:

df *= 100
df = pandas.DataFrame(df, dtype=str)
df += '%'

ew = pandas.ExcelWriter('test.xlsx')
df.to_excel(ew)
ew.save()
Answered By: Saullo G. P. Castro

This is the solution I arrived at using pandas with OpenPyXL v2.2, and ensuring cells contain numbers at the end, and not strings. Keep values as floats, apply format at the end cell by cell (warning: not efficient):

xlsx = pd.ExcelWriter(output_path)
df.to_excel(xlsx, "Sheet 1")
sheet = xlsx.book.worksheets[0]
for col in sheet.columns[1:sheet.max_column]:
    for cell in col[1:sheet.max_row]:
        cell.number_format = '0.00%'
        cell.value /= 100 #if your data is already in percentages, has to be fractions
xlsx.save()

See OpenPyXL documentation for more number formats.

Interestingly enough, the docos suggest that OpenPyXL is smart enough to guess percentages from string formatted as “1.23%”, but this doesn’t happen for me. I found code in Pandas’ _Openpyxl1Writer that uses “set_value_explicit” on strings, but nothing of the like for other versions. Worth further investigation if somebody wants to get to the bottom of this.

Answered By: Mike Demenok

The XlsxWriter docs have a helpful example of how to achieve this:
https://xlsxwriter.readthedocs.io/example_pandas_percentage.html

Here’s the gist:

writer = pd.ExcelWriter('pandas_percent.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1')
percent_format = writer.book.add_format({'num_format': '0%'})
# Now apply the number format to the column with index 2.
writer.sheets['Sheet1'].set_column(2, 2, None, percent_format)
writer.save()

Note 1: The column you want to format as a percent must be a ratio float (i.e. do not multiply it by 100).
Note 2: The parameter in the set_column() call that is set to None is the column width. If you want to automatically fit the column width check out this post:
https://stackoverflow.com/a/61617835/13261722.
Note 3: If you want more on the set_column() function you can check out the docs:
https://xlsxwriter.readthedocs.io/worksheet.html?highlight=set_column#set_column

Answered By: Colin Middleton
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.