pandas
apply function
python
data analysis
indexing

getting the index of a row in a pandas apply function

Master System Design with Codemia

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

Introduction

When you use DataFrame.apply(..., axis=1) in pandas, each row is passed to your function as a Series. The row index is already there: you access it with row.name.

That is the simplest answer, but it is also a good reminder that apply is row-wise Python code, not a special vectorized engine. If you only need the index for a transformation, row.name is convenient. If you need performance on large data, it is often worth looking for a vectorized alternative.

The Basic Pattern

Here is the direct way to access the row index.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {"value": [10, 20, 30]},
5    index=["a", "b", "c"]
6)
7
8
9def describe_row(row):
10    return f"index={row.name}, value={row['value']}"
11
12
13df["description"] = df.apply(describe_row, axis=1)
14print(df)

row.name contains the index label for that row.

What row.name Actually Is

Inside a row-wise apply, row is a Series representing one row. Its .name attribute is the row index label.

If your index is numeric, row.name may look like an integer. If your index is a string or datetime index, row.name is that label type instead.

That means the technique works across normal index types without special handling.

Example With a Numeric Index

python
1import pandas as pd
2
3df = pd.DataFrame({"value": [5, 7, 9]})
4
5
6def f(row):
7    return row.name * row["value"]
8
9
10df["result"] = df.apply(f, axis=1)
11print(df)

If the index is 0, 1, 2, then row.name gives those positions.

MultiIndex Case

If the DataFrame uses a MultiIndex, row.name becomes a tuple.

python
1import pandas as pd
2
3index = pd.MultiIndex.from_tuples([("A", 1), ("A", 2), ("B", 1)])
4df = pd.DataFrame({"value": [10, 20, 30]}, index=index)
5
6
7def f(row):
8    group, item = row.name
9    return f"group={group}, item={item}, value={row['value']}"
10
11
12df["info"] = df.apply(f, axis=1)
13print(df)

That is often cleaner than resetting the index just to get at the labels.

When apply Is Not the Best Tool

apply(axis=1) is easy to read, but it is relatively slow because it executes Python code row by row.

If you only need the index values for a vectorized computation, consider:

  • 'df.index'
  • 'df.reset_index()'
  • direct column operations instead of row-wise apply

For example, if you want the index as a column, this is often simpler:

python
df = df.reset_index().rename(columns={"index": "row_id"})

Now the former index is a regular column and can participate in vectorized expressions.

Why row.name Is Still Useful

Despite the performance caveat, row.name is very handy when the row logic is genuinely custom and the index is part of the business rule.

Examples include:

  • generating row-specific labels
  • comparing index values with row content
  • building per-row lookup keys

In those situations, it is the idiomatic answer.

Common Pitfalls

A common mistake is expecting a separate “row index argument” to be passed automatically into the function. In pandas, the row label is already available on the row Series as name.

Another mistake is assuming row.name is always an integer position. It is the index label, which may be a string, timestamp, or tuple.

Developers also overuse apply(axis=1) for operations that could be vectorized much faster.

Finally, after reset_index(), the old index becomes ordinary data. If you change the DataFrame shape afterward, make sure you know whether you still want the original labels or the new default index.

Summary

  • Inside DataFrame.apply(..., axis=1), the row index is available as row.name.
  • 'row.name returns the index label, not necessarily a numeric position.'
  • For MultiIndex, row.name is typically a tuple.
  • Use apply for custom row logic, but prefer vectorized alternatives when performance matters.
  • If you want the index as ordinary data, reset_index() is often a cleaner design.

Course illustration
Course illustration

All Rights Reserved.