Series vs DataFrame
A first look at pandas' two core structures — the 1D Series and the 2D DataFrame — how they relate, and how to tell which one you have.
Everything in pandas is built from two objects. Learn their shapes now and every later chapter becomes easier: a Series is like one column of a scorecard, and a DataFrame is the whole scorecard.
Definition
A Series is a one-dimensional labelled array that holds values of a single data type, together with an index (the row labels) and an optional name.
A DataFrame is a two-dimensional labelled table made of rows and columns, where each column is a Series and all columns share the same index.
- One-dimensional (Series) — just a list of values going down; it has a length but no columns.
- Two-dimensional (DataFrame) — rows and columns, like an Excel sheet or a SQL table.
- Index — the labels on the left. Both structures have one; in a DataFrame all columns share it.
- Each column is a Series — select one column from a DataFrame and you get a Series back. Select one row and you also get a Series (whose index is the column names).
Diagram
text
Series DataFrame
index values index player team runs <- column names
┌───────┬──────┐ ┌──────┬────────┬──────┬──────┐
│ Kohli │ 973 │ │ 0 │ Kohli │ RCB │ 973 │
│Buttler│ 863 │ │ 1 │ Buttler│ RR │ 863 │
│ Rahul │ 670 │ │ 2 │ Rahul │ PBKS │ 670 │
└───────┴──────┘ └──────┴────────┴──────┴──────┘
name: "runs" │ │ │
dtype: int64 Series Series Series
(each column is a Series,
all sharing the same index)Syntax
python
pd.Series(data=None, index=None, dtype=None, name=None)
pd.DataFrame(data=None, index=None, columns=None, dtype=None)| Parameter | Meaning | Default |
|---|---|---|
data | the values: list, NumPy array, dict, scalar (Series); dict of lists, list of dicts, 2D array… (DataFrame) | None (empty) |
index | row labels | RangeIndex 0, 1, 2, … |
columns | column names (DataFrame only) | dict keys, or 0, 1, 2, … |
dtype | force a data type | inferred from the data |
name | a name for the Series (Series only) | None |
Both constructors get a full chapter of their own — this topic is just the overview.
Example — one of each
python
import pandas as pd
runs = pd.Series([973, 863, 670], index=["Kohli", "Buttler", "Rahul"], name="runs")
print(runs)
print(type(runs))text
Kohli 973
Buttler 863
Rahul 670
Name: runs, dtype: int64
<class 'pandas.Series'>A printed Series shows index on the left, values on the right, then a footer with the name and dtype.
python
df = pd.DataFrame({
"player": ["Virat Kohli", "Jos Buttler", "KL Rahul", "Shubman Gill"],
"team": ["RCB", "RR", "PBKS", "GT"],
"season": [2016, 2022, 2020, 2023],
"runs": [973, 863, 670, 890],
"average": [81.08, 57.53, 55.83, 59.33],
})
print(type(df))
print(type(df["runs"]))
print(df["runs"])text
<class 'pandas.DataFrame'>
<class 'pandas.Series'>
0 973
1 863
2 670
3 890
Name: runs, dtype: int64How it works: df["runs"] pulls one column out of the DataFrame. It comes back as a Series whose name is the column name (runs) and whose index is the DataFrame's index (0–3).
Example — a row is also a Series
python
print(df.loc[0])text
player Virat Kohli
team RCB
season 2016
runs 973
average 81.08
Name: 0, dtype: objectHow it works: .loc[0] selects the row whose label is 0. The result is a Series where the index is the column names and the name is the row label (0). Because a row mixes text and numbers, its dtype has to be the general object.
Comparison
| Series | DataFrame | |
|---|---|---|
| Dimensions | 1 (ndim = 1) | 2 (ndim = 2) |
| Shape | (n,) | (rows, columns) |
| Looks like | one column / one list | a whole table / spreadsheet |
| Labels | index only | index and columns |
| Data type | one dtype (.dtype) | one dtype per column (.dtypes) |
Has a name? | yes (.name) | no — its columns have names |
df["col"] returns | — | a Series |
df[["col"]] returns | — | a DataFrame (one column) |
| NumPy analogue | 1D array with labels | 2D table of labelled 1D arrays |
Common mistakes
- ❌
pd.series(...)orpd.dataframe(...). ✅ Class names are capitalised:pd.Series,pd.DataFrame(capital F too). - ❌ Expecting
df["runs"]to return a DataFrame. ✅ Single brackets → Series; double bracketsdf[["runs"]]→ DataFrame. - ❌ Thinking a Series has columns. ✅ A Series has only an index and values;
series.columnsraisesAttributeError. - ❌ Using
.dtypeon a DataFrame. ✅ A DataFrame has.dtypes(plural) — one per column.
Interview tip
Q: What is the relationship between a Series and a DataFrame?
A: A DataFrame is a collection of Series that share the same index — one Series per column. Selecting a single column (df["col"]) or a single row (df.loc[label]) returns a Series.
Key points to remember
- A Series is a 1D labelled array with a single dtype, an index and an optional name.
- A DataFrame is a 2D labelled table; each column is a Series and all columns share one index.
- df['col'] returns a Series; df[['col']] (double brackets) returns a DataFrame.
- A single row from df.loc[label] is also a Series — its index is the column names.
- Series has .dtype (one type); DataFrame has .dtypes (one per column).
- The class names are pd.Series and pd.DataFrame — capital S, capital D and F.
Try it yourself
Series and DataFrame side by side
A column and a row are both Series
Practice: Series or DataFrame?
Revision Flashcards
Tap a card to flip it and see the answer.
