Every single thing you do in pandas happens inside one of two objects: the Series and the DataFrame. Get a clear mental model of what each one is and how they relate, and the rest of the library stops feeling like a pile of unrelated methods. This tutorial builds that model with small, runnable examples you can type yourself.
The short version: a Series is one column, a DataFrame is a whole table, and a DataFrame is literally a bundle of Series sharing the same row labels. Once that clicks, selecting data, computing statistics and reshaping tables all follow naturally.
The Series: one labelled column
A Series is a one-dimensional array of values, each paired with a label called the index. Think of it as a single column lifted out of a spreadsheet, but with its own row labels attached. You create one from a list:
import pandas as pd
ages = pd.Series([24, 31, 28, 45, 22], name="age")
print(ages)
0 24
1 31
2 28
3 45
4 22
Name: age, dtype: int64
The left column is the index (0 to 4 here, assigned automatically), the right column is the values, and dtype: int64 tells you these are whole numbers. A Series knows how to compute on itself:
print(ages.mean())
print(ages.max())
30.0
45
You can also give a Series meaningful labels instead of the default integers, which is where its power over a plain list shows:
scores = pd.Series([88, 72, 95], index=["Aarti", "Bhaskar", "Chitra"])
print(scores["Bhaskar"])
72
Now the index acts like a lookup key. This label-based alignment is the single feature that makes pandas different from raw NumPy arrays.
The DataFrame: many Series, one index
A DataFrame is a two-dimensional table: rows and columns, where every column is a Series and all columns share the same index. The most common way to build one is from a dictionary where each key becomes a column. This is small illustrative sample data:
import pandas as pd
data = {
"name": ["Aarti", "Bhaskar", "Chitra", "Devan"],
"city": ["Hyderabad", "Hyderabad", "Bengaluru", "Pune"],
"age": [24, 31, 28, 45],
"salary": [48000, 65000, 52000, 90000],
}
df = pd.DataFrame(data)
print(df)
name city age salary
0 Aarti Hyderabad 24 48000
1 Bhaskar Hyderabad 31 65000
2 Chitra Bengaluru 28 52000
3 Devan Pune 45 90000
The four columns are four Series, all glued together by the shared index 0 to 3. You can confirm the relationship by pulling one column out:
print(type(df["salary"]))
<class 'pandas.core.series.Series'>
A single column really is a Series. That is why every Series method you learned above works on any column of any DataFrame.
Moving between the two
Selecting columns is where the Series/DataFrame distinction bites beginners, so make it explicit. Single brackets give a Series; double brackets give a DataFrame:
print(df["age"].mean()) # Series -> a number
print(df[["name", "salary"]]) # list of columns -> DataFrame
32.0
name salary
0 Aarti 48000
1 Bhaskar 65000
2 Chitra 52000
3 Devan 90000
The rule to remember: pass a string to get one column as a Series; pass a list of strings to get a DataFrame, even if that list has one item. Some methods only exist on one type, so knowing which you are holding saves confusion.
The index ties everything together
Every Series and DataFrame carries an index, and pandas uses it to align data automatically during operations. By default you get a RangeIndex (0, 1, 2, …), but you can promote a meaningful column to be the index:
df2 = df.set_index("name")
print(df2.loc["Chitra"])
city Bengaluru
age 28
salary 52000
Name: Chitra, dtype: object
With name as the index you can look up a whole row by label. Notice the returned row is itself a Series, with the former column names now acting as its index. This symmetry, columns of a row and rows of a column both being Series, is the elegant core of pandas.
Practical usage
In real analysis you rarely build DataFrames by hand; you read them from files. But you constantly reach into them for single Series to compute a statistic, apply a transformation, or feed a chart. A typical workflow looks like: load a DataFrame, select the column you care about as a Series, compute or clean it, then assign the result back as a new column. Understanding that a column is a Series makes every one of those steps intuitive rather than magical.
Common mistakes
- Using single brackets when you need a DataFrame.
df["col"]is a Series; some downstream code expects a DataFrame and breaks. Usedf[["col"]]when a table is required. - Assuming positional access works everywhere. After
set_index,df.loc["Chitra"]uses the label, not a position. Mixing label and position access is a frequent source of confusion, which thelocandiloctutorial resolves. - Ignoring index alignment. When you add two Series with different indexes, pandas aligns by label and fills mismatches with NaN. This surprises beginners who expect element-by-element math like plain lists.
- Rebuilding an index accidentally. Operations like
reset_index()change row labels; if later code relies on the old labels it will fail silently.
In interviews
Expect the direct question "what is the difference between a Series and a DataFrame?" Answer crisply: a Series is one-dimensional labelled data, a DataFrame is a two-dimensional table whose columns are Series sharing an index. Interviewers may follow up on how selecting a column returns a Series, or ask what the index is for, so mention automatic label alignment. Being fluent about these structures signals that you understand pandas from the ground up rather than just memorizing recipes.
Where this fits in your learning path
This tutorial sits right after the pandas introduction in the data analytics path. With the Series and DataFrame clear in your head, the natural next step is precise row and column selection in pandas loc and iloc. If you want to understand the array machinery underneath, the NumPy introduction shows the foundation pandas is built on. These structures are the bedrock of the data analyst toolkit.
Frequently Asked Questions
What is the difference between a pandas Series and DataFrame?
How do I create a DataFrame in pandas?
What is the index in a pandas DataFrame?
How do I get a single column from a DataFrame?
Can a DataFrame column hold different data types?
Want to Build Your Career in Data Analytics with AI?
Join CodeBegun and train with working industry engineers — View the Data Analytics curriculum

