Skip to content
Laviyx Learn

Try

Python for Data course menu

pandas Series Explained: Create, Index and Analyse

Learn the pandas Series: a labelled one-dimensional array, creating a Series from lists and dictionaries, the index, selecting by label and position, vectorised operations, value_counts and handy summary methods.

Beginner10 min readUpdated
On this page

pandas is the library for working with tables in Python. It has two core objects:

  • a Series: one column of values with labels;
  • a DataFrame: a table made of Series that share the same labels (next lesson).

A Series is like a NumPy array with an index: a label for every value.

Creating a Series#

Python
import pandas as pd

temps = pd.Series([22.5, 25.1, 19.8, 27.3])
print(temps)
print(temps.index)
print(temps.values)
Output
0    22.5
1    25.1
2    19.8
3    27.3
dtype: float64
RangeIndex(start=0, stop=4, step=1)
[22.5 25.1 19.8 27.3]

The left column is the index (0, 1, 2, 3 by default), the right column the values, and the last line shows the dtype. .values gives the underlying NumPy array.

Meaningful labels#

Labels can be anything: names, dates, product codes. Pass them as index, or build the Series from a dictionary:

Python
import pandas as pd

temps = pd.Series([22.5, 25.1, 19.8, 27.3], index=["Mon", "Tue", "Wed", "Thu"], name="temp_c")
print(temps)
print(temps["Wed"])

population = pd.Series({"Mumbai": 12.4, "Delhi": 11.0, "Pune": 3.1})
print(population)
Output
Mon    22.5
Tue    25.1
Wed    19.8
Thu    27.3
Name: temp_c, dtype: float64
19.8
Mumbai    12.4
Delhi     11.0
Pune       3.1
dtype: float64

Selecting values: loc and iloc#

Because a Series has both labels and positions, pandas gives you two explicit selectors:

  • .loc[...] selects by label;
  • .iloc[...] selects by position (0, 1, 2, …).
Python
import pandas as pd

temps = pd.Series([22.5, 25.1, 19.8, 27.3], index=["Mon", "Tue", "Wed", "Thu"])
print(temps.loc["Tue"])
print(temps.iloc[0])
print(temps.loc["Tue":"Thu"])     # label slices INCLUDE the end
print(temps.iloc[1:3])            # position slices EXCLUDE the end
Output
25.1
22.5
Tue    25.1
Wed    19.8
Thu    27.3
dtype: float64
Tue    25.1
Wed    19.8
dtype: float64

Label slices include their end label; position slices work like Python's and exclude the end. Using loc and iloc explicitly avoids ambiguity, especially when the labels are numbers.

Vectorised operations and alignment#

Arithmetic works on every value, like NumPy. When combining two Series, pandas lines them up by label, not by position:

Python
import pandas as pd

temps = pd.Series([22.5, 25.1, 19.8], index=["Mon", "Tue", "Wed"])
print((temps * 9 / 5 + 32).round(1))

jan = pd.Series({"Asha": 120, "Ravi": 90, "Meera": 150})
feb = pd.Series({"Ravi": 110, "Asha": 100, "John": 80})
print(jan + feb)
Output
Mon    72.5
Tue    77.2
Wed    67.6
dtype: float64
Asha     220.0
John       NaN
Meera      NaN
Ravi     200.0
dtype: float64

"Asha" is matched with "Asha" even though the order differs. Names present in only one Series get NaN (missing), because there is nothing to add. Use jan.add(feb, fill_value=0) to treat missing as zero.

Filtering and summarising#

Python
import pandas as pd

scores = pd.Series([88, 72, 95, 64, 81], index=["Asha", "Ravi", "Meera", "John", "Priya"])
print(scores[scores >= 80])
print(scores.mean(), scores.max(), scores.idxmax())
print(scores.sort_values(ascending=False).head(3))
print(scores.describe())
Output
Asha     88
Meera    95
Priya    81
dtype: int64
80.0 95 Meera
Meera    95
Asha     88
Priya    81
dtype: int64
count     5.000000
mean     80.000000
std      12.349089
min      64.000000
25%      72.000000
50%      81.000000
75%      88.000000
max      95.000000
dtype: float64

idxmax() returns the label of the maximum. describe() gives a quick statistical summary.

Counting categories#

value_counts is one of the most used methods in pandas: how many times each value appears.

Python
import pandas as pd

payment = pd.Series(["card", "upi", "cash", "upi", "card", "upi"])
print(payment.value_counts())
print(payment.value_counts(normalize=True).round(2))
print(payment.nunique(), payment.unique())
Output
upi     3
card    2
cash    1
Name: count, dtype: int64
upi     0.50
card    0.33
cash    0.17
Name: proportion, dtype: float64
3 ['card' 'upi' 'cash']

normalize=True gives proportions instead of counts.

Common mistakes#

Practice#

Practice exercise

Monthly expenses are {"rent": 15000, "food": 6200, "travel": 1800, "phone": 600, "fun": 2400}. Create a Series, print the total, the share of each category as a percentage (rounded to 1 decimal), and the categories above 2000 sorted from largest to smallest.

Show hint

Divide the Series by its sum and multiply by 100. Filter with a boolean condition, then sort_values(ascending=False).

Show solution
Python
import pandas as pd

expenses = pd.Series({"rent": 15000, "food": 6200, "travel": 1800, "phone": 600, "fun": 2400})
print(expenses.sum())
print((expenses / expenses.sum() * 100).round(1))
print(expenses[expenses > 2000].sort_values(ascending=False))
Output
26000
rent      57.7
food      23.8
travel     6.9
phone      2.3
fun        9.2
dtype: float64
rent    15000
food     6200
fun      2400
dtype: int64

Key takeaway#

Next: whole tables, in DataFrames.

Finished this lesson?