Pandas
DataFrame
Python
Data Analysis
Python List

Pandas DataFrame to List of Dictionaries

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The standard way to convert a pandas DataFrame into a list of row dictionaries is df.to_dict(orient="records"). It produces one dictionary per row, which is usually the right shape for JSON payloads, API responses, templating, and any code that expects ordinary Python objects instead of pandas structures.

Use orient="records" for row dictionaries

DataFrame.to_dict supports several output shapes, but records is the one that returns a list of dictionaries keyed by column name.

python
1import pandas as pd
2
3df = pd.DataFrame({
4    "name": ["Alice", "Bob"],
5    "age": [30, 25],
6    "city": ["Toronto", "Montreal"],
7})
8
9records = df.to_dict(orient="records")
10print(records)

Output:

text
[{'name': 'Alice', 'age': 30, 'city': 'Toronto'}, {'name': 'Bob', 'age': 25, 'city': 'Montreal'}]

This is concise, fast, and usually better than writing a manual row loop.

Know what the other orientations mean

Developers often get unexpected results because they call to_dict() without the right orientation. For example, the default orientation gives a dictionary of columns, not a list of row dictionaries.

python
1import pandas as pd
2
3df = pd.DataFrame({"name": ["Alice", "Bob"], "age": [30, 25]})
4print(df.to_dict())

That output is useful for some tasks, but it is not the same as records. If the downstream consumer expects a list of objects, use orient="records" deliberately.

Handle missing values before conversion if needed

Pandas may carry NaN, NaT, or nullable types that are fine inside a DataFrame but awkward in plain Python structures or JSON serialization. If you care about how missing values are represented, clean them before conversion.

python
1import pandas as pd
2
3df = pd.DataFrame({
4    "name": ["Alice", "Bob"],
5    "score": [91, None],
6})
7
8clean = df.where(pd.notnull(df), None)
9records = clean.to_dict(orient="records")
10print(records)

That produces None instead of pandas missing markers, which is often friendlier for API work.

Convert only the columns you need

If the DataFrame is wide, slice it first and then convert. That keeps the result smaller and makes the contract explicit.

python
1import pandas as pd
2
3df = pd.DataFrame({
4    "name": ["Alice", "Bob"],
5    "age": [30, 25],
6    "city": ["Toronto", "Montreal"],
7    "active": [True, False],
8})
9
10records = df[["name", "active"]].to_dict(orient="records")
11print(records)

This is usually better than converting everything and then deleting keys from every dictionary afterward.

Manual loops are valid, but usually not necessary

You can build the list manually with iterrows() or itertuples(), but that is usually the right choice only when you need custom per-row transformation logic.

python
1import pandas as pd
2
3df = pd.DataFrame({"name": ["Alice", "Bob"], "age": [30, 25]})
4
5records = []
6for _, row in df.iterrows():
7    records.append({"name": row["name"], "age_group": "adult" if row["age"] >= 18 else "minor"})
8
9print(records)

For straight conversion, to_dict(orient="records") is clearer and usually faster.

Watch index handling

The DataFrame index is not included in orient="records" output unless you first turn it into a column. If the index carries meaningful information, make that explicit.

python
1import pandas as pd
2
3df = pd.DataFrame({"value": [10, 20]}, index=["a", "b"])
4records = df.reset_index(names="id").to_dict(orient="records")
5print(records)

That is the cleanest way to preserve index information in row dictionaries.

Common Pitfalls

  • Calling to_dict() without orient="records" and getting a column-oriented structure instead.
  • Forgetting that the DataFrame index is omitted unless you reset it into a column.
  • Passing pandas missing values straight into code that expects plain None.
  • Using iterrows() for simple conversions that pandas already handles directly.
  • Converting more columns than the downstream consumer actually needs.

Summary

  • Use df.to_dict(orient="records") for a list of row dictionaries.
  • Slice columns first when you only need part of the DataFrame.
  • Clean missing values before conversion if plain Python None is important.
  • Reset the index first if the index should appear in the output.
  • Reserve manual row loops for cases where each row needs custom transformation.

Course illustration
Course illustration

All Rights Reserved.