Creating a DataFrame
Build DataFrames from a dict of lists, a list of dicts, a list of lists with column names, a NumPy array, or several Series — and know what each one does with missing data.
Watch the lesson
1 video on CodeWithMunnaX
In real projects you usually load a DataFrame from a file (pd.read_csv), but building one by hand is a core skill: you do it to test ideas, to create small lookup tables (team → home ground), to turn API results (lists of dicts) into a table, and to understand how pandas thinks about rows and columns. pandas accepts many input shapes — each one maps to rows and columns in a slightly different way.
Definition
A DataFrame is a two-dimensional, size-mutable table with labelled rows (the index) and labelled columns, where each column is a Series that can hold its own data type.
pd.DataFrame(...)is the constructor that builds one from Python or NumPy data.
- Two-dimensional — data is arranged in rows and columns, like an Excel sheet or a SQL table.
- Size-mutable — you can add or remove columns and rows after creation.
- Labelled rows and columns — rows have index labels (default
0, 1, 2, …), columns have names (default0, 1, 2, …if you don't give any). - Own data type per column —
playercan bestrwhilerunsisint64in the same table.
Syntax
python
pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=None)| Parameter | Meaning | Default |
|---|---|---|
data | dict of lists/Series, list of dicts, list of lists/tuples, 2D NumPy array, another DataFrame | None → empty DataFrame |
index | row labels (one per row) | RangeIndex 0…n-1 (or the Series' / dict keys' labels) |
columns | column names; for a dict, selects and orders keys | dict keys, or 0, 1, 2, … |
dtype | force one dtype for all columns | inferred per column |
copy | copy the input data | None (pandas decides) |
Example 1 — dict of lists (most common)
python
import pandas as pd
df = pd.DataFrame({
"player": ["Rohit", "Virat", "Gill", "Pant"],
"team": ["MI", "RCB", "GT", "DC"],
"runs": [45, 78, 12, 101],
})
print(df)text
player team runs
0 Rohit MI 45
1 Virat RCB 78
2 Gill GT 12
3 Pant DC 101How it works: each key becomes a column name and each list becomes that column's values. This is column-oriented input. All lists must have the same length — otherwise ValueError: All arrays must be of the same length. A single scalar is repeated for every row: {"player": ["Rohit", "Virat"], "season": 2024} gives 2024 in both rows.
Example 2 — list of dicts (one dict per row)
python
rows = [
{"player": "Bumrah", "team": "MI", "wickets": 3},
{"player": "Rashid", "team": "GT", "wickets": 2},
{"player": "Chahal", "wickets": 4},
]
print(pd.DataFrame(rows))text
player team wickets
0 Bumrah MI 3
1 Rashid GT 2
2 Chahal NaN 4How it works: this is row-oriented input — the format JSON APIs return. Each dict is one row, and the union of all keys becomes the columns. Chahal's dict has no team, so pandas fills NaN instead of failing.
Note:
pd.DataFrame({"player": "Rohit", "runs": 45})(a dict of only scalars) raisesValueError: If using all scalar values, you must pass an index. Wrap it in a list —pd.DataFrame([{"player": "Rohit", "runs": 45}])— or passindex=[0].
Example 3 — list of lists + column names
python
data = [["Rohit", "MI", 45], ["Virat", "RCB", 78], ["Gill", "GT", 12]]
print(pd.DataFrame(data))
print(pd.DataFrame(data, columns=["player", "team", "runs"], index=["p1", "p2", "p3"]))text
0 1 2
0 Rohit MI 45
1 Virat RCB 78
2 Gill GT 12
player team runs
p1 Rohit MI 45
p2 Virat RCB 78
p3 Gill GT 12How it works: each inner list is a row. Without columns=, pandas names the columns 0, 1, 2 — almost never what you want, so always pass columns. index= sets custom row labels. Tuples of tuples and list(zip(names, runs)) work the same way.
Example 4 — NumPy 2D array
python
import numpy as np
rng = np.random.default_rng(42)
arr = rng.integers(0, 50, size=(3, 4))
print(pd.DataFrame(arr, columns=["over_1", "over_2", "over_3", "over_4"], index=["MI", "CSK", "RCB"]))text
over_1 over_2 over_3 over_4
MI 4 38 32 21
CSK 21 42 4 34
RCB 10 4 26 48How it works: a (3, 4) array becomes 3 rows × 4 columns. Because a NumPy array has one dtype, every column gets that dtype (int64 here). This is the bridge from your NumPy work into pandas.
Example 5 — from Series (aligned by index)
python
runs = pd.Series([45, 78, 12], index=["Rohit", "Virat", "Gill"])
sixes = pd.Series([3, 2], index=["Virat", "Pant"])
print(pd.DataFrame({"runs": runs, "sixes": sixes}))
print(runs.to_frame(name="runs"))text
runs sixes
Gill 12.0 NaN
Pant NaN 2.0
Rohit 45.0 NaN
Virat 78.0 3.0
runs
Rohit 45
Virat 78
Gill 12How it works: with a dict of Series, the index labels become the row labels and pandas aligns the Series — the row index is the union of all labels, and a player missing from one Series gets NaN in that column (this is the same alignment you saw for Series arithmetic). series.to_frame() turns a single Series into a one-column DataFrame.
Which input should I use?
| Input | Orientation | Column names come from | Missing data |
|---|---|---|---|
| dict of lists | column by column | dict keys | lists must be equal length |
| list of dicts | row by row | union of dict keys | missing keys → NaN |
| list of lists / tuples | row by row | columns= (else 0, 1, 2…) | rows must be equal length |
| 2D NumPy array | row by row | columns= (else 0, 1, 2…) | one dtype for all columns |
| dict of Series | column by column | dict keys | aligned by index → NaN |
Common mistakes
- ❌ Lists of different lengths in a dict →
ValueError: All arrays must be of the same length. ✅ Pad withNoneor build row by row (list of dicts). - ❌ Forgetting
columns=with a list of lists → columns named0, 1, 2. ✅ Always name them. - ❌
pd.DataFrame({"player": "Rohit", "runs": 45}). ✅ Wrap the dict in a list:pd.DataFrame([{...}]). - ❌
pd.Dataframe(...)orpd.dataframe(...). ✅ Capital D and F:pd.DataFrame. - ❌ Putting a list inside a list-of-dicts value (
{"Name": ["A", "B"]}in a list) and expecting 2 rows. ✅ That creates one row whose cell holds a whole list.
Interview tip
Q: What is the difference between building a DataFrame from a dict of lists and from a list of dicts? A: A dict of lists is column-oriented — keys are columns and all lists must have the same length. A list of dicts is row-oriented — each dict is a row, columns are the union of keys, and missing keys become NaN. APIs and JSON usually give you a list of dicts.
Key points to remember
- pd.DataFrame(data, index, columns, dtype) builds a 2D labelled table with one dtype per column.
- Dict of lists: keys → columns, lists → values; all lists must be the same length.
- List of dicts: each dict is a row; missing keys become NaN.
- List of lists or a 2D NumPy array: each inner list is a row — always pass columns=.
- Dict of Series: rows are aligned by index labels; unmatched labels become NaN.
- A dict of only scalars needs an index (or wrap it in a list).
- series.to_frame() turns a Series into a one-column DataFrame.
Try it yourself
Dict of lists vs list of dicts
List of lists and a NumPy array
From Series, and common errors
Practice: your playing XI table
Revision Flashcards
Tap a card to flip it and see the answer.
