In the previous part we saw an interesting example of slicing. Let’s use the same example again:
import numpy as np
import pandas as pd
nums = pd.Series([2.35, 4.11, 0.87, 2.76, 3.12, 5.79],
index = ['A', 'B', 'C', 'D', 'E', 'F'])
nums
Now, we can slice the Series object using the explicit label indices:
nums['B':'E']
or the implicit positional indices:
nums[1:4]
As you remember, the second index is included if we use label indices, but not if we use the positional ones. This may cause confusion if the label indices are integers too. Have a look at this modified example:
nums = pd.Series([2.35, 4.11, 0.87, 2.76, 3.12, 5.79],
index = [1, 2, 3, 4, 5, 6])
First, let’s try to access an element by index. Suppose we’re interested in the element with the value 4.11. It’s label index is 2, but it’s implicit positional index is 1. So, which one should we use? Let’s find out:
# using the label index
nums[2]
# using the positional index
nums[1]
Looks like the label index rules. So, if we want to make a slice from the element with the value 4.11 to the element with the value 2.76, including the latter, we should use the label indices, remembering that the second one is included, right? Let’s check it out:
nums[2:4]
Disappointed? Looks like this time the positional, not the label index rules. So, when we index a Series object, the label index is used, but when we slice it, the positional index is the one that matters. Pretty confusing. So, is there a way to always use only the label index or always use the positional one? There is. This is where indexers come in really handy, and in particular the indexers loc and iloc.
The indexers are attributes that tell the Series object how it should be indexed. Here’s how they work:
loc – always use the explicit label index iloc – always use the implicit positional integer index
So, it’s always better to use the indexers to make our code clear, especially if the indices are integers. And now have a look at the indexers in action:
# here's our nums Series object again
nums = pd.Series([2.35, 4.11, 0.87, 2.76, 3.12, 5.79],
index = [1, 2, 3, 4, 5, 6])
# just to see the difference clearly, let's index it without the indexers again
nums[3]
# and let's slice it without the indexers
nums[2:4]
So, the label index is used with indexing and the positional one with slicing. Now let’s use just the label indices in both indexing and slicing. We need the loc attribute to this end:
# indexing with loc
nums.loc[3]
# slicing with loc
nums.loc[2:4]
As you can see, now the label index is used in both cases. And now let’s use just the positional indices, just like in a regular Python list:
# indexing with iloc
nums.iloc[3]
# slicing with iloc
nums.iloc[2:4]
The indexers are also used with DataFrames, which we are going to see in the next part of the series.
Here’s the video version of the article: