Creating DataFrames

Reviewed & published by Brayan K

Creating a DataFrame means turning raw Python data — dictionaries, lists, or NumPy arrays — into a labelled table using the pd.DataFrame(...) constructor, choosing the input shape that best matches your data.

Part of the free Pandas course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Real data arrives in many shapes. In this lesson you'll learn every common way to hand data to Pandas and get a clean table back.

What You'll Learn in This Lesson

1 Dict of Lists vs List of Dicts

The two most common inputs map onto how your data is organised:

📦 Dict of lists — column-oriented

Each key is a column, each list is that column's values.

📋 List of dicts — row-oriented

Each dict is one row; keys become the column names.

import pandas as pd

# Method 1: dict of lists (column-oriented)
by_columns = pd.DataFrame({
    "name": ["Alice", "Bob"],
    "age": [25, 30],
})

# Method 2: list of dicts (row-oriented) — same result
by_rows = pd.DataFrame([
    {"name": "Alice", "age": 25},
    {"name": "Bob", "age": 30},
])

print(by_columns)
print(by_rows.equals(by_columns))   # True — identical tables

# Output:
#     name  age
# 0  Alice   25
# 1    Bob   30
# True

# ✅ Expected output:
#     name  age
# 0  Alice   25
# 1    Bob   30
# True

2 List of Lists with columns=

If your data is a plain grid of values — a list where each inner list is one row — pass it directly and name the columns with columns=:

rows = [
    ["Alice", 25],
    ["Bob", 30],
]
df = pd.DataFrame(rows, columns=["name", "age"])
import pandas as pd

# A grid of values — one inner list per row
rows = [
    ["Alice", 25, "London"],
    ["Bob", 30, "Paris"],
    ["Carol", 35, "Berlin"],
]

df = pd.DataFrame(rows, columns=["name", "age", "city"])
print(df)

# Output:
#     name  age    city
# 0  Alice   25  London
# 1    Bob   30   Paris
# 2  Carol   35  Berlin

# ✅ Expected output:
#     name  age    city
# 0  Alice   25  London
# 1    Bob   30   Paris
# 2  Carol   35  Berlin

3 From a NumPy Array (and Custom Index)

Numerical data often starts life as a NumPy array. Pass the 2-D array as the first argument, then label the rows and columns with index= and columns=:

arr = np.array([[1, 2], [3, 4]])
df = pd.DataFrame(arr, columns=["a", "b"], index=["r1", "r2"])

The index= argument sets custom row labels instead of the default 0, 1, 2, ....

import pandas as pd
import numpy as np

# A 2-D NumPy array of numbers
arr = np.array([
    [85, 90],
    [78, 88],
    [92, 95],
])

# Label rows with index= and columns with columns=
df = pd.DataFrame(arr, columns=["math", "science"], index=["Ana", "Ben", "Cara"])
print(df)

# Output:
#       math  science
# Ana     85       90
# Ben     78       88
# Cara    92       95

# ✅ Expected output:
#       math  science
# Ana     85       90
# Ben     78       88
# Cara    92       95
import pandas as pd

data = {
    "city": ["London", "Paris", "Berlin"],
    "temp": [15, 18, 12],
}

# 🎯 YOUR TURN: build the DataFrame and give the rows
# the custom labels "A", "B", "C" using the index= argument
df = pd.DataFrame(data, index=___)   # replace ___ with a list of 3 labels
print(df)

# Expected output:
#      city  temp
# A  London    15
# B   Paris    18
# C  Berlin    12

📋 Quick Reference

InputConstructor
Dict of listspd.DataFrame({...})
List of dictspd.DataFrame([{...}, ...])
List of listspd.DataFrame(rows, columns=[...])
NumPy arraypd.DataFrame(arr, columns=[...])
Custom row labelspd.DataFrame(data, index=[...])

🎯 Mini Challenge: Survey Records

Imagine survey responses arriving one record at a time as dictionaries:

import pandas as pd

records = [
    {"name": "Ana", "score": 8},
    {"name": "Ben", "score": 6},
    {"name": "Cara", "score": 9},
]

df = pd.DataFrame(records)
print(df)
print("Shape:", df.shape)

# Output:
#    name  score
# 0   Ana      8
# 1   Ben      6
# 2  Cara      9
# Shape: (3, 2)

# ✅ Expected output:
#    name  score
# 0   Ana      8
# 1   Ben      6
# 2  Cara      9
# Shape: (3, 2)

❓ Frequently Asked Questions

Lesson complete — you can build any DataFrame!

You've created DataFrames from dicts of lists, lists of dicts, lists of lists with named columns, and NumPy arrays — and you can set a custom index too.

Practice quiz

What constructor builds every kind of DataFrame in this lesson?

  • pd.make_frame(...)
  • pd.create(...)
  • pd.DataFrame(...)
  • pd.table(...)

Answer: pd.DataFrame(...). All four approaches use the same pd.DataFrame(...) constructor.

In a dict of lists like {'name':[...], 'age':[...]}, what does each key become?

  • A column
  • A row
  • An index label
  • A data type

Answer: A column. A dict of lists is column-oriented: each key is a column and its list holds that column's values.

In a list of dicts, what does each dictionary become?

  • A column
  • The index
  • A dtype
  • One row, with keys as column names

Answer: One row, with keys as column names. A list of dicts is row-oriented: each dict is one row and its keys become columns.

When is a list of dicts the most natural input?

  • When you already have whole columns ready
  • When records arrive row by row, like from an API or database
  • When the data is a NumPy array
  • Never

Answer: When records arrive row by row, like from an API or database. Row-by-row records map cleanly onto a list of dicts; missing keys become NaN.

If you pass a list of lists without columns=, what are the column labels?

  • Integers 0, 1, 2, ...
  • The first row's values
  • Letters A, B, C
  • An error

Answer: Integers 0, 1, 2, .... Without columns=, pandas labels the columns 0, 1, 2, ... — almost never what you want.

How do you give a NumPy-array-backed DataFrame meaningful column names?

  • It happens automatically
  • Use df.rename only
  • Pass columns=[...] to the constructor
  • You cannot

Answer: Pass columns=[...] to the constructor. Pass columns= (and optionally index=) so the otherwise unnamed columns get labels.

Which argument sets custom row labels instead of the default 0,1,2...?

  • columns=
  • index=
  • labels=
  • rows=

Answer: index=. index= sets the row labels; you can also promote a column with set_index.

Do a dict-of-lists and an equivalent list-of-dicts produce the same table?

  • No, they always differ
  • Only for numeric data
  • Only with index= set
  • Yes, the resulting DataFrames are identical

Answer: Yes, the resulting DataFrames are identical. Both inputs build the same DataFrame; .equals() confirms they are identical.

What does pd.DataFrame(records).shape return for 3 records of 2 keys each?

  • (2, 3)
  • (3, 2)
  • (3, 3)
  • (2, 2)

Answer: (3, 2). shape is (rows, columns): 3 rows and 2 columns gives (3, 2).

How do you promote an existing column to be the index?

  • df.index('column')
  • df.reindex()
  • df.set_index('column')
  • df.columns = 'column'

Answer: df.set_index('column'). df.set_index('column') makes that column the row index.

Continue this course

Frequently asked questions

What are the main ways to create a Pandas DataFrame?

The four most common are: from a dictionary of lists (columns), from a list of dictionaries (rows), from a list of lists with an explicit columns= argument, and from a NumPy array. All use the same pd.DataFrame(...) constructor.

When should I use a dict of lists vs a list of dicts?

Use a dict of lists when your data is naturally column-oriented (you have whole columns ready). Use a list of dicts when your data comes row by row — for example records from an API or database, where each record is one dictionary.

How do I set a custom index on a DataFrame?

Pass index= to the constructor, e.g. pd.DataFrame(data, index=['a','b','c']), or call df.set_index('column') to promote an existing column to the index.

Can I build a DataFrame from a NumPy array?

Yes. Pass the 2-D array as the first argument and supply columns= (and optionally index=) so the otherwise unnamed rows and columns get meaningful labels.