Series

pandas · Essentials · 10 min

Every DataFrame column is a Series, so its behaviour underlies everything you do in pandas.

pandas is imported as import pandas as pd. Its simplest structure is the Series: a one-dimensional array of values (usually backed by a NumPy array) paired with an index, a sequence of labels for those values, plus an optional name.

You can build one from a list, where the index defaults to 0, 1, 2, ..., or from a dict, where the keys become the index:

s = pd.Series({"apples": 3, "pears": 5})

A Series feels like a mix of a NumPy array and a dict. Like an array, it has a dtype, supports vectorized arithmetic (s * 2), comparisons and NumPy ufuncs (np.log(s)), and has methods such as sum, mean, max, idxmax. Like a dict, you can look values up by label, test "apples" in s (which checks the index, not the values) and iterate over s.items().

Unlike NumPy, aggregations skip missing values by default: pd.Series([1, None, 3]).mean() is 2.0, not NaN.

To be explicit about how you look something up, use s.loc["apples"] for labels and s.iloc[0] for positions. Plain s[0] on a Series with a non-integer index is ambiguous; it was positional with a deprecation warning in pandas 2.x and is label-only from pandas 3.0, so avoid it.

s.index and s.values give the two halves; prefer s.to_numpy() over s.values when you need a NumPy array. Operations that return a Series keep the index, which is how labels follow your data through a computation.

Example

import numpy as np
import pandas as pd

stock = pd.Series({"apples": 3, "pears": 5, "plums": 0}, name="stock")
print(stock)
# apples    3
# pears     5
# plums     0
# Name: stock, dtype: int64

print(stock.loc["pears"], stock.iloc[0])   # 5 3
print("pears" in stock, 5 in stock)        # True False (checks the index)
print(stock[stock > 0].index.tolist())     # ['apples', 'pears']
print((stock * 1.5).idxmax())              # pears

t = pd.Series([21.5, np.nan, 23.5])
print(t.mean())                            # 22.5  (NaN skipped)
print(t.to_numpy())                        # [21.5  nan 23.5]

Remember

  • A Series is values + index labels + dtype + optional name
  • Vectorized maths works like NumPy; aggregations skip NaN by default
  • Use .loc for labels and .iloc for positions
  • in tests the index, not the values

Watch out for

  • Writing s[0] and assuming it means 'first element': use s.iloc[0].

Check yourself

  1. `s = pd.Series([10, 20], index=['a', 'b'])`. What is `20 in s`?
  2. What is `pd.Series([2.0, None, 4.0]).sum()`?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: pandas.pydata.org/docs/user_guide/dsintro.html#series