pandas
Series
element index
Python
data analysis

Find element's index in pandas Series

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Finding the index of an element in a pandas Series depends on what you need: the first occurrence, all occurrences, or the index of the min/max value. Unlike Python lists, pandas Series have labeled indices (not just positional integers), so "index" can mean either the label or the integer position. The most common methods are boolean indexing with bracket notation, idxmin()/idxmax() for extremes, and Index.get_loc() for label-based lookups.

Finding the Index of a Specific Value

python
1import pandas as pd
2
3s = pd.Series([10, 20, 30, 20, 40], index=["a", "b", "c", "d", "e"])
4
5# Find the index label(s) where value equals 20
6result = s[s == 20].index
7print(result)  # Index(['b', 'd'], dtype='object')
8
9# Get the first matching index label
10first_idx = s[s == 20].index[0]
11print(first_idx)  # b
12
13# Get as a list
14all_indices = s[s == 20].index.tolist()
15print(all_indices)  # ['b', 'd']

Boolean indexing (s == 20) creates a mask, and .index returns the labels of matching elements.

Using Index.get_loc() for Positional Index

python
1s = pd.Series([10, 20, 30, 40, 50])
2
3# Get the integer position of the label (not the value)
4pos = s.index.get_loc(2)
5print(pos)  # 2 (because default index is 0, 1, 2, 3, 4)
6
7# For custom index labels
8s2 = pd.Series([10, 20, 30], index=["a", "b", "c"])
9pos = s2.index.get_loc("b")
10print(pos)  # 1

get_loc() returns the positional integer for a given label. This is useful when you need the position for slicing with .iloc.

Finding Index of Min and Max Values

python
1s = pd.Series([15, 8, 23, 4, 19], index=["a", "b", "c", "d", "e"])
2
3# Index label of the minimum value
4print(s.idxmin())  # d (value 4)
5
6# Index label of the maximum value
7print(s.idxmax())  # c (value 23)
8
9# Integer position of min/max
10print(s.values.argmin())  # 3
11print(s.values.argmax())  # 2

idxmin() and idxmax() return the index label. argmin() and argmax() on the underlying NumPy array return the integer position.

Using np.where for Condition-Based Indices

python
1import numpy as np
2
3s = pd.Series([10, 20, 30, 20, 40])
4
5# Integer positions where value == 20
6positions = np.where(s == 20)[0]
7print(positions)  # [1, 3]
8
9# Integer positions where value > 15
10positions = np.where(s > 15)[0]
11print(positions)  # [1, 2, 3, 4]
12
13# Convert positions to index labels
14labels = s.index[positions]
15print(labels)  # Index([1, 3], dtype='int64')

np.where() returns integer positions, which can be mapped to labels via s.index[positions].

Searching String Values

python
1s = pd.Series(["apple", "banana", "cherry", "banana", "date"])
2
3# Exact match
4print(s[s == "banana"].index.tolist())  # [1, 3]
5
6# Partial match (contains)
7print(s[s.str.contains("an")].index.tolist())  # [1, 3]
8
9# Starts with
10print(s[s.str.startswith("c")].index.tolist())  # [2]
11
12# Case-insensitive match
13print(s[s.str.lower() == "apple"].index.tolist())  # [0]

Working with MultiIndex

python
1arrays = [["A", "A", "B", "B"], [1, 2, 1, 2]]
2index = pd.MultiIndex.from_arrays(arrays, names=["letter", "number"])
3s = pd.Series([10, 20, 30, 40], index=index)
4
5# Find index of value 30
6result = s[s == 30].index
7print(result)  # MultiIndex([('B', 1)], names=['letter', 'number'])
8
9# Access specific level
10print(result.get_level_values("letter"))  # Index(['B'], dtype='object')
11print(result.get_level_values("number"))  # Index([1], dtype='int64')

Finding the Index of the Closest Value

python
1s = pd.Series([1.0, 2.5, 3.7, 5.1, 8.3])
2
3target = 3.5
4
5# Find the index of the value closest to target
6closest_idx = (s - target).abs().idxmin()
7print(closest_idx)          # 2
8print(s[closest_idx])       # 3.7

This pattern subtracts the target, takes absolute values, and finds the index of the minimum difference.

Performance Comparison

python
1import timeit
2
3s = pd.Series(range(1_000_000))
4target = 500_000
5
6# Boolean indexing
7%timeit s[s == target].index[0]          # ~2 ms
8
9# np.where
10%timeit np.where(s == target)[0][0]      # ~1.5 ms
11
12# isin (for multiple values)
13%timeit s[s.isin([target])].index[0]     # ~5 ms

For single-value lookups on large Series, np.where is slightly faster. For readability, boolean indexing is preferred.

Common Pitfalls

  • Confusing index labels with integer positions: A Series with custom labels like ["a", "b", "c"] has labels at positions 0, 1, 2. s["b"] returns the value at label "b", while s.iloc[1] returns the value at position 1. When finding an "index", clarify whether you need the label or the position.
  • Assuming idxmin() returns the position: idxmin() and idxmax() return the index label, not the integer position. Use s.values.argmin() for the position. If the index labels happen to be integers, this distinction is easy to miss.
  • Getting an empty result without checking: s[s == value].index[0] raises IndexError if no element matches. Always check len(s[s == value]) first, or use .index[0] if len(...) > 0 else None.
  • Duplicate index labels: If a Series has duplicate index labels, s.loc["a"] may return multiple values. get_loc() returns a slice or boolean array instead of a single integer. Handle duplicates explicitly.
  • Using s.index(value) like a Python list: Pandas Series does not have an index() method like Python lists. Calling s.index returns the Index object (all labels), not a search function. Use boolean indexing or np.where instead.

Summary

  • Use s[s == value].index to get index labels matching a value
  • Use idxmin() / idxmax() for the label of the min/max value
  • Use np.where(s == value)[0] for integer positions
  • Use s.values.argmin() / s.values.argmax() for positional min/max
  • Use (s - target).abs().idxmin() to find the nearest value
  • Always distinguish between index labels and integer positions — they are different in custom-indexed Series

Course illustration
Course illustration

All Rights Reserved.