0Pricing
Pandas & NumPy Academy · Lesson

Label-Based and Position-Based Access

Retrieve elements with .loc (label) and .iloc (integer position) and understand the difference between the two.

Label-Based and Position-Based Access is a free Pandas & NumPy Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Pandas & NumPy Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Two Ways to Access Series Elements

Pandas provides two primary accessors for selecting elements from a Series: .loc for label-based access and .iloc for integer position-based access. Understanding which to use and when is critical — using the wrong one on an integer-indexed Series produces confusing results, and Pandas 2.0 deprecated many ambiguous direct bracket usages.

import pandas as pd

s = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
print(s.loc['b'])    # 20  -- by label
print(s.iloc[1])     # 20  -- by position

.loc: Label-Based Access

.loc accesses elements by their index label. You can pass a single label (returns a scalar), a list of labels (returns a Series), or a slice of labels (inclusive on both ends, unlike Python slices). If the label does not exist, Pandas raises a KeyError. Use .loc when labels are meaningful (dates, names, IDs).

import pandas as pd

s = pd.Series([10, 20, 30, 40, 50],
              index=['a', 'b', 'c', 'd', 'e'])

print(s.loc['c'])          # 30
print(s.loc[['a', 'c']])   # a:10 c:30
print(s.loc['b':'d'])      # b:20 c:30 d:40 -- inclusive

.iloc: Position-Based Access

.iloc accesses elements by their integer position (0-based), completely ignoring the index labels. This behaves like Python list indexing: negative positions count from the end, and slices follow Python's exclusive-stop convention. Use .iloc when you need the 'n-th' element regardless of its label.

import pandas as pd

s = pd.Series([10, 20, 30, 40, 50],
              index=['a', 'b', 'c', 'd', 'e'])

print(s.iloc[2])          # 30  -- third element
print(s.iloc[-1])         # 50  -- last element
print(s.iloc[1:4])        # b:20 c:30 d:40 -- exclusive stop

When .loc and .iloc Differ

The difference matters most for integer-labelled Series. If a Series has index labels [5, 10, 15], then s.loc[5] returns the element with label 5 (the first element) while s.iloc[5] raises an IndexError (only 3 elements exist). Always choose based on whether you mean 'the element labelled X' or 'the X-th element'.

import pandas as pd

s = pd.Series([100, 200, 300], index=[5, 10, 15])
print(s.loc[10])   # 200  -- element with label 10
print(s.iloc[1])   # 200  -- second element
# s.loc[1] would raise KeyError -- no label 1

Selecting Multiple Labels with .loc

Pass a list to .loc to select multiple elements in any order, potentially with repetitions. The result is a new Series with the same labels as the list you provided. This is similar to fancy indexing in NumPy but aligned on index labels rather than positions. It is commonly used to reorder or subset columns in analytical pipelines.

import pandas as pd

s = pd.Series({'Jan': 100, 'Feb': 200, 'Mar': 300, 'Apr': 400})

# Select Q1 months in reverse order
print(s.loc[['Mar', 'Feb', 'Jan']])
# Mar    300
# Feb    200
# Jan    100

Label Slicing with .loc

Unlike Python slices, .loc slices are inclusive on both ends. s.loc['b':'d'] returns elements with labels b, c, and d. This can be surprising if you are used to Python's exclusive-stop convention. Make sure the labels you slice between actually exist in the index, or the slice will return unexpected results silently.

import pandas as pd

s = pd.Series(range(5), index=['a', 'b', 'c', 'd', 'e'])
print(s.loc['b':'d'])
# b    1
# c    2
# d    3
# dtype: int64
# Note: 'd' is INCLUDED (inclusive stop)

Boolean Indexing with .loc

You can pass a boolean Series to .loc to filter elements. The boolean Series must have the same index as the target Series. This is the Pandas equivalent of NumPy boolean masking and supports compound conditions with & and |. It is the standard way to filter rows in DataFrames too.

import pandas as pd

s = pd.Series([3, 7, 2, 9, 1], index=['a', 'b', 'c', 'd', 'e'])
print(s.loc[s > 4])
# b    7
# d    9
# dtype: int64

Setting Values with .loc and .iloc

Both .loc and .iloc can appear on the left side of an assignment to modify values in place. This is the correct pattern — using chained indexing like s['a'] = 99 may trigger a SettingWithCopyWarning in DataFrames. For Series, direct label access is generally safe, but .loc is explicit and recommended.

import pandas as pd

s = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
s.loc['b'] = 99
print(s)
# a    10
# b    99
# c    30

Bracket Access on a Series

Direct bracket notation s['label'] works for label access and is equivalent to s.loc['label'] for string indices. For integer indices the behaviour is ambiguous and was changed in Pandas 2.0 — it now always means label access. For clarity and future-proof code, always use .loc or .iloc explicitly rather than relying on bracket disambiguation.

import pandas as pd

s = pd.Series([10, 20, 30], index=['x', 'y', 'z'])
print(s['y'])      # 20  -- label access via brackets
print(s.loc['y']) # 20  -- explicit and preferred

Accessing Elements from DatetimeIndex

When a Series has a DatetimeIndex, .loc accepts partial date strings for convenient range selection. s.loc['2023'] returns all elements from 2023, and s.loc['2023-01':'2023-06'] returns the first half of 2023. This is one of Pandas' most ergonomic features for time series work.

import pandas as pd

dates = pd.date_range('2023-01-01', periods=5, freq='ME')
values = pd.Series([10, 20, 30, 40, 50], index=dates)
print(values.loc['2023-03':'2023-05'])
# 2023-03-31    30
# 2023-04-30    40
# 2023-05-31    50

at and iat for Single Element Speed

.at[label] and .iat[position] are optimised scalar accessors — faster than .loc and .iloc when accessing a single element in a tight loop, because they skip the overhead of returning a Series object. They cannot select multiple elements. Use them when you need maximum performance for repeated single-element lookups.

import pandas as pd

s = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
print(s.at['b'])    # 20  -- label scalar access
print(s.iat[2])     # 30  -- position scalar access

Quick Check

Test your understanding of .loc and .iloc from this lesson.

Lesson Recap

In this lesson you learned: .loc accesses elements by index label with inclusive slice stops, .iloc accesses elements by integer position with exclusive slice stops like Python lists, and .at and .iat are faster scalar accessors for single-element lookups in loops. Next up we explore vectorized operations on Series and how Pandas handles index alignment automatically.

Frequently asked questions

Is the “Label-Based and Position-Based Access” lesson free?

Yes — the full text of “Label-Based and Position-Based Access” is free to read here on the web, and the Pandas & NumPy Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Pandas & NumPy Academy course, upgrade to CoddyKit PRO.

What will I learn in “Label-Based and Position-Based Access”?

Retrieve elements with .loc (label) and .iloc (integer position) and understand the difference between the two. You practise Pandas & NumPy Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Pandas & NumPy Academy?

No prior experience is required. Pandas & NumPy Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Label-Based and Position-Based Access” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Pandas & NumPy Academy lesson?

Yes. Every Pandas & NumPy Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Creating a Series
  2. Label-Based and Position-Based Access
  3. Vectorized Operations on Series
  4. Useful Series Methods
← Back to Pandas & NumPy Academy