How do I format numbers in a DataFrame for presentation in pandas?
Short answer
Use the Styler through df.style.format to control how numbers are displayed without changing the underlying values. Formatting for display and rounding the data are different things, and only one is safe.
The short version
Use df.style.format(...) to control how values are displayed without altering them. This keeps full precision in the data while showing a clean table. Rounding the actual values with df.round() changes your data and should be avoided until the very end, if at all.
Formatting for display
import pandas as pd
df = pd.DataFrame({
"city": ["Leeds", "Bath"],
"amount": [1234.5678, 987.6543],
"share": [0.1234, 0.8766],
})
styled = df.style.format({
"amount": "{:,.2f}", # thousands separator, two decimals
"share": "{:.1%}", # as a percentage
})
The amount now displays as 1,234.57 and share as 12.3%, while the stored numbers keep their full precision.
Why this matters more than it seems
Rounding your data to make it look nice destroys information and compounds errors. If you round to two decimals and then sum, the total can differ from the sum of the unrounded values. Formatting affects only the presentation layer, so every calculation still uses the exact numbers and only the final display is tidy.
The rule: round for the eye, never for the maths.
Highlighting values
The Styler can also apply conditional formatting, which is useful for drawing attention in a report.
df.style.format({"amount": "{:,.2f}"}) \
.highlight_max(subset=["amount"], color="lightgreen") \
.bar(subset=["share"], color="lightblue")
highlight_max shades the largest value, and bar draws in-cell bars proportional to the value, which conveys the distribution at a glance.
Hiding the index
The default integer index is rarely meaningful in a presented table.
df.style.hide(axis="index")
Where it renders
The Styler produces HTML, so it displays in a notebook and can be exported.
styled.to_html("report.html")
styled.to_excel("report.xlsx") # formatting carries into Excel
It does not affect a plain print(df) in a terminal, which shows the raw values. So the Styler is a tool for notebooks, HTML reports and Excel output, not for console scripts.
Keep the data and the presentation separate
The broader principle is worth holding on to. Your DataFrame is data: exact, unformatted, suitable for computation. The formatted table is a view of it, produced at the end for a human. Mixing the two, by storing formatted strings in the frame, is a common mistake that turns numbers into text and silently breaks every subsequent calculation.
df["amount"] = df["amount"].map("{:,.2f}".format) # DON'T: now it is text
df["amount"].sum() # fails or concatenates, because these are strings now
Format at the boundary, and keep the numbers as numbers everywhere else.