In short
Half of early Pandas confusion is not knowing whether you're holding a table or a single column. Get this one distinction right and the error messages start making sense.
A DataFrame is Pandas' 2D table structure (rows and columns); a Series is a single column — understanding this distinction clears up most early Pandas confusion.

Think of it like this
The cricket scorecard
The full scorecard, with batters as rows and runs, balls and fours as columns, is a DataFrame. Read just the 'runs' column top to bottom and you have a Series. The batting order number on the left is the index, the label for each row.
Watch it happen
What's inside a DataFrame
1/4A DataFrame is the whole table: rows, columns and labels.
The big ideas
What you need to know
DataFrame = 2D
Rows and columns. Has .shape like (11, 4) and .columns listing the names.
Series = 1D
One column with an index. df["runs"] gives a Series, df[["runs"]] gives a one-column DataFrame.
.loc uses labels
df.loc["Kohli", "runs"] picks by row and column name. Slices with .loc include the end label.
.iloc uses positions
df.iloc[0, 1] is first row, second column. Works like Python lists, end excluded.
See it in code
Walk through the code
1import pandas as pd2 3score = pd.DataFrame(4 {"runs": [82, 45, 12], "balls": [53, 38, 9]},5 index=["Kohli", "Gill", "Pant"],6)7 8runs = score["runs"] # Series9print(type(runs))10print(score.loc["Gill", "runs"]) # 4511print(score.iloc[0, 1]) # 5312score["strike_rate"] = score["runs"] / score["balls"] * 1001/4Keys become column names. The index gives each row a readable label.
Build a DataFrame from a dictionary, pull out a Series, and pick cells by label and by position.
Save yourself the pain
Common mistakes
Oops
Expecting df["runs"] to behave like a table and calling DataFrame-only methods on it.
Do this instead
Check type(). Use df[["runs"]] with double brackets if you really need a DataFrame.
Oops
Mixing up .loc and .iloc after filtering, when the index is no longer 0, 1, 2.
Do this instead
Use .iloc for positions and .loc for labels, or reset_index(drop=True) after filtering.
Your mission
Your team's scorecard
Quick check
What does df[["runs"]] return, compared to df["runs"]?
Go deeper
- 1Practice extracting a single column as a Series and note what changes.
- 2Learn to select data by label (.loc) versus by position (.iloc).
- 3Build a DataFrame from scratch using a Python dictionary.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.