The Series
Overview
A column with labels attached, and the labels travel with the data.
What You Will Learn in This Lesson
By the end of this lesson, you will be able to:
- Build a Series with an index and read a value by its label.
- Say what a Series has that a numpy array does not.
- Use the numpy operations you already know on a Series.
- Tell
maxfromidxmax, and know which question each answers.
Why This Matters
A DataFrame is a collection of Series, so everything here is the foundation for the next six units. The index in particular is not decoration: it is what survives a filter, what lines two columns up when you add them, and what turns "the highest score" into "who got the highest score".
Step 1: A labelled column
A Series is one column of values plus an index. Build one from a list and pandas supplies 0, 1, 2 as the index; supply your own and the labels become how you reach the values.
Values and labels together
The index is printed down the left. Reaching for a label gives you the value beside it, in the same way a dictionary key would.
import pandas as pd
scores = pd.Series([92, 88, 79], index=["Ada", "Grace", "Alan"])
print(scores)
print(scores["Grace"])
The labels survive what you do to it
This is the part that matters. Filter the Series and the surviving values keep their own labels, so you never have to track which position belonged to whom.
import pandas as pd
scores = pd.Series([92, 88, 79], index=["Ada", "Grace", "Alan"])
high = scores[scores > 85]
print(high)
print(list(high.index))
Mini Practice #1: Reach by label
Try It YourselfPrint Alan’s score, then every score above 80 with its label, then the list of labels that survived.
Step 2: Everything numpy did, a Series does too
Masks, arithmetic and aggregation all carry over unchanged. What is added is that the labels come with them.
The familiar operations
If unit 3 made sense, none of this is new. A Series is an array with an index bolted on.
import pandas as pd
scores = pd.Series([92, 88, 79], index=["Ada", "Grace", "Alan"])
print(scores.mean())
print(scores + 5)
print(scores[scores > 85])
Two different questions
max gives the value. idxmax gives the label of the row it was on. Confusing them is easy and the wrong one is never an error, just a wrong answer.
import pandas as pd
scores = pd.Series([92, 88, 79], index=["Ada", "Grace", "Alan"])
print(scores.max()) # what the best score was
print(scores.idxmax()) # who got it
Alignment, and where NaN comes from
Adding two Series matches them on their labels, not their positions. A label present in one and missing from the other gives NaN — which is either exactly what you wanted or the quietest bug in pandas.
import pandas as pd
term1 = pd.Series([90, 80], index=["Ada", "Grace"])
term2 = pd.Series([70, 60], index=["Grace", "Alan"])
print(term1 + term2)
Nothing is out of order and nothing raised. Ada and Alan are NaN because each appears in only one of the two terms.
Mini Practice #2: Watch the alignment
Try It YourselfPredict what this prints before you run it. Then reorder the second Series and confirm the answer does not change.
Step 3: When to Use It
One labelled column
Values with meaningful labels — scores by name, sales by month — where lookups use the label.
scores = pd.Series([92, 88], index=["Ada", "Grace"])
Arithmetic that should align
Two Series combine by label, so values match up even when the order differs.
When Not to Use It
Do not assume two Series line up by position. They align by label, and a label missing from one side produces NaN rather than an error.
End-of-Lesson Exercises
Exercise 1: Who scored highest
Write top_scorer(scores) that takes a Series of scores indexed by name and returns the name of the highest scorer.
idxmax gives the label of the largest value; max would give you the value itself, which is the other question.
Exercise 2: Above their own average
Write above_average(scores) that takes a Series indexed by name and returns a list of the names whose score is strictly above the mean of the Series. Keep the labels; do not work with positions.
Mask the Series with scores > scores.mean(), then read .index off what survives and turn it into a list.