CSV
df.to_csv('output.csv', index=False)
index=False
Without it, pandas writes the index as an unnamed first column. Re-import that file and you get a stray Unnamed: 0 column — and it compounds every round trip.
df.to_csv('output.csv', index=False, encoding='utf-8-sig')
utf-8-sig makes Excel display accented characters correctly rather than as mojibake.
Excel
df.to_excel('report.xlsx', index=False, sheet_name='Summary')
Several sheets in one workbook:
with pd.ExcelWriter('report.xlsx') as writer:
summary.to_excel(writer, sheet_name='Summary', index=False)
detail.to_excel(writer, sheet_name='Detail', index=False)
by_region.to_excel(writer, sheet_name='Regions', index=False)
The with block handles saving and closing — a common way to end up with a corrupt file is writing sheets without it.
Figures
fig.savefig('chart.png', dpi=150, bbox_inches='tight')
fig.savefig('chart.svg', bbox_inches='tight') # vector, scales cleanly
dpi=150 is a reasonable screen and document default; 300 for print. SVG stays sharp at any size, which is the better choice for anything going into a slide deck.
Rounding before export
df.round({'revenue': 2, 'margin': 3}).to_csv('output.csv', index=False)
Saves whoever opens it from 1250.7599999999998, which looks like carelessness even though it is just floating point.