to_dict, to_html & to_excel
Turn a DataFrame into Python dictionaries (every to_dict orient), an HTML table for a web page, or an Excel workbook with to_excel.
Not every export is a file. Sometimes your Flask/FastAPI backend needs plain Python dicts to return as JSON, a web page needs an HTML table, and a team manager wants an Excel report. Munna's notebook lists the export family like this:
| Method | Produces | Typical use |
|---|---|---|
to_csv() | CSV file / text | data sharing |
to_dict() | Python dict / list | backend logic |
to_excel() | Excel workbook | reports |
to_html() | HTML <table> | web display |
to_json() | JSON text | APIs |
This topic covers to_dict, to_html and to_excel.
Definition
DataFrame.to_dict(orient)converts a DataFrame into native Python objects (dicts and lists) arranged according toorient.to_html()renders the DataFrame as an HTML<table>string, andto_excel()writes it to a sheet in an Excel workbook.
- Native Python objects — after
to_dictyou are out of pandas: plaindict/listyou can loop over,json.dumps, or return from an API. - orient — just like in
to_json, it decides the nesting: by columns, by rows, as lists, and so on. - HTML string —
to_html()returns text containing<table>,<thead>,<tr>,<td>tags; with a path it saves a.htmlfile you can open in a browser.
Syntax
python
df.to_dict(orient="dict")
df.to_html(buf=None, index=True, columns=None, classes=None, border=None)
df.to_excel(excel_writer, sheet_name="Sheet1", index=True)| Parameter | Meaning | Default |
|---|---|---|
orient (to_dict) | "dict", "list", "records", "index", "split", "tight", "series" | "dict" |
buf (to_html) | file path / buffer to write to; None returns a string | None |
index (to_html, to_excel) | include the row index | True |
classes (to_html) | extra CSS class names for the <table> tag | None |
excel_writer (to_excel) | file path or pd.ExcelWriter object | required |
sheet_name (to_excel) | name of the sheet to write | "Sheet1" |
Example — every to_dict orient
python
import pandas as pd
df = pd.DataFrame({"player": ["Virat Kohli", "Travis Head"],
"team": ["RCB", "SRH"], "runs": [741, 567]})
for o in ["dict", "list", "records", "index", "split", "tight"]:
print(o, "->", df.to_dict(orient=o))text
dict -> {'player': {0: 'Virat Kohli', 1: 'Travis Head'}, 'team': {0: 'RCB', 1: 'SRH'}, 'runs': {0: 741, 1: 567}}
list -> {'player': ['Virat Kohli', 'Travis Head'], 'team': ['RCB', 'SRH'], 'runs': [741, 567]}
records -> [{'player': 'Virat Kohli', 'team': 'RCB', 'runs': 741}, {'player': 'Travis Head', 'team': 'SRH', 'runs': 567}]
index -> {0: {'player': 'Virat Kohli', 'team': 'RCB', 'runs': 741}, 1: {'player': 'Travis Head', 'team': 'SRH', 'runs': 567}}
split -> {'index': [0, 1], 'columns': ['player', 'team', 'runs'], 'data': [['Virat Kohli', 'RCB', 741], ['Travis Head', 'SRH', 567]]}
tight -> {'index': [0, 1], 'columns': ['player', 'team', 'runs'], 'data': [['Virat Kohli', 'RCB', 741], ['Travis Head', 'SRH', 567]], 'index_names': [None], 'column_names': [None]}| orient | Result shape | When to use |
|---|---|---|
"dict" (default) | {col: {index: value}} | look up d["runs"][0] |
"list" | {col: [values]} | the same shape you'd pass to pd.DataFrame(...); chart libraries |
"records" | [{col: value}, ...] | one dict per row — APIs, looping over rows |
"index" | {index: {col: value}} | look up a whole row by its label |
"split" / "tight" | index, columns and data stored separately | rebuild the exact DataFrame later |
"series" | {col: Series} | rarely needed |
How it works: notice that unlike JSON, the index keys stay real Python ints (0, 1), not strings. A very common trick is turning two columns into a lookup dict: df.set_index("player")["runs"].to_dict() gives {'Virat Kohli': 741, 'Travis Head': 567}.
Example — to_html
python
print(df.to_html(index=False))text
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th>player</th>
<th>team</th>
<th>runs</th>
</tr>
</thead>
<tbody>
<tr>
<td>Virat Kohli</td>
<td>RCB</td>
<td>741</td>
</tr>
<tr>
<td>Travis Head</td>
<td>SRH</td>
<td>567</td>
</tr>
</tbody>
</table>How it works: column names go into <th> cells inside <thead>, and each row becomes a <tr> with <td> cells. The table gets class="dataframe" so you can style it with CSS; add your own with classes="table table-striped" (Bootstrap). df.to_html("points_table.html") saves a file you can double-click to open in a browser. (Jupyter's pretty table display uses this same HTML behind the scenes.)
Example — to_excel (not runnable in the browser)
Writing .xlsx needs openpyxl, which the playground doesn't include. On your own computer:
python
path = r"C:\Users\Admin\Desktop\data\ipl_report.xlsx"
df.to_excel(path, index=False) # one sheet called "Sheet1"
df.to_excel(path, sheet_name="Orange Cap", index=False)
# several sheets in ONE workbook -> use ExcelWriter
with pd.ExcelWriter(path) as writer:
batting.to_excel(writer, sheet_name="Batting", index=False)
bowling.to_excel(writer, sheet_name="Bowling", index=False)How it works: calling to_excel(path) twice on the same path overwrites the file each time — the second sheet replaces the first. To put several DataFrames into one workbook, open a pd.ExcelWriter in a with block and pass the writer to each to_excel call.
Common mistakes
- ❌ Looping
for row in df.to_dict():and getting column names. ✅ The default orient is by columns; useorient="records"to get one dict per row. - ❌ Calling
df.to_excel(path, sheet_name=...)twice expecting two sheets. ✅ Use onepd.ExcelWriterfor multiple sheets. - ❌
to_html()output shows the 0, 1, 2 index column on your web page. ✅ Passindex=False. - ❌
ModuleNotFoundError: No module named 'openpyxl'. ✅pip install openpyxl.
Interview tip
Q: How do you convert a DataFrame to a list of dictionaries, one per row?
A: df.to_dict(orient="records"). This is the standard way to return DataFrame rows from a Python web API, because each dict maps directly to a JSON object.
Key points to remember
- to_dict() converts a DataFrame to plain Python dicts/lists; orient decides the nesting.
- orient='records' gives one dict per row; 'list' gives {column: [values]}; the default 'dict' gives {column: {index: value}}.
- df.set_index('a')['b'].to_dict() builds a quick lookup dictionary from two columns.
- to_html() returns an HTML <table> string (or saves a .html file); use index=False and classes= for styling.
- to_excel() needs openpyxl; sheet_name names the sheet and index=False drops the index.
- Write several sheets into one workbook with a pd.ExcelWriter in a with block.
Try it yourself
to_dict orients
Lookup dict from two columns
to_html for a web page
to_excel with several sheets (run on your own computer)
import pandas as pd
# Needs: pip install openpyxl (not available in the browser playground)
batting = pd.DataFrame({"player": ["Virat Kohli", "Travis Head"], "runs": [741, 567]})
bowling = pd.DataFrame({"bowler": ["Harshal Patel", "Jasprit Bumrah"], "wickets": [24, 20]})
path = r"C:\Users\Admin\Desktop\data\ipl_report.xlsx"
with pd.ExcelWriter(path) as writer:
batting.to_excel(writer, sheet_name="Batting", index=False)
bowling.to_excel(writer, sheet_name="Bowling", index=False)
print("Done")Not runnable in the in-browser playground — try it locally.
Practice: build an API response
Revision Flashcards
Tap a card to flip it and see the answer.
