pandas
DataFrame
set cell value
Python
indexing

Set value for particular cell in pandas DataFrame using index

Master System Design with Codemia

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

Introduction

Updating one cell in a pandas DataFrame sounds simple, but the right accessor depends on whether you are targeting a label or a numeric position. Using the correct tool keeps the code fast, clear, and free from the chained-assignment bugs that often confuse new pandas users. For single-cell updates, the main choices are .at, .iat, .loc, and .iloc.

Setting a value by index label with .at

Use .at when you know the row label and the column label. It is designed for scalar access, which makes it a good fit for updating one cell.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "order_id": [101, 102, 103],
6        "status": ["new", "new", "shipped"],
7        "total": [19.99, 34.50, 8.25],
8    }
9).set_index("order_id")
10
11df.at[102, "status"] = "paid"
12print(df)

Because order_id is the index, the row selector is 102, not the second row position. This distinction matters whenever your index labels are not simple 0, 1, 2 values.

Setting a value by numeric position with .iat

If you want the second row and third column regardless of labels, use .iat. It works with integer positions and is also optimized for single-value access.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "name": ["Ada", "Grace", "Linus"],
6        "team": ["platform", "data", "infra"],
7        "score": [88, 91, 79],
8    }
9)
10
11df.iat[1, 2] = 95
12print(df)

In this example, row position 1 refers to "Grace" and column position 2 refers to "score". .iat is useful when you are working in loops or algorithms where positions are already known.

Using .loc and .iloc when the update is part of a larger selection

.loc and .iloc can also update a single cell, but they are more general-purpose selectors. Use them when you may later expand from one cell to a slice or a conditional update.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "employee_id": [10, 11, 12],
6        "department": ["sales", "support", "sales"],
7        "bonus": [500, 400, 450],
8    }
9).set_index("employee_id")
10
11df.loc[12, "bonus"] = 600
12print(df)

That reads naturally when the row key and column label are meaningful. The position-based equivalent is .iloc.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "city": ["Toronto", "Montreal", "Ottawa"],
6        "temperature": [2, -1, 0],
7    }
8)
9
10df.iloc[0, 1] = 5
11print(df)

For a single cell, .at and .iat are slightly more direct, but .loc and .iloc are handy when your selection logic may grow beyond one scalar.

Choosing the accessor

Use label-based access when the index carries business meaning, such as an order number or employee id. Use position-based access when the location is derived from iteration, sorting, or algorithmic offsets.

If performance matters and you are updating many individual cells, .at and .iat are usually the best scalar choices. That said, if you are making many updates, vectorized assignment is often a better design than a Python loop over cells.

Common Pitfalls

The biggest source of confusion is mixing up index labels and row positions. If the index is 101, 102, 103, then .at[1, "status"] looks for label 1, not the first row. Use .iat or .iloc for positional access.

Another common problem is chained assignment, such as writing to a filtered slice and assuming the original frame changed. Patterns like df[df["status"] == "new"]["total"] = 0 can produce a warning and unreliable behavior. Instead, use .loc on the original DataFrame.

Duplicate index values are another trap. .at expects a scalar lookup, so duplicated labels can produce confusing behavior or force you to use .loc instead. If you want one row per key, keep the index unique.

Finally, watch data types. Assigning a string into a numeric column can upcast the entire column to object dtype, which may hurt later calculations.

Summary

  • Use .at[row_label, column_label] for one cell by label.
  • Use .iat[row_position, column_position] for one cell by position.
  • '.loc and .iloc also work and are useful when selection logic may expand.'
  • Do not confuse index labels with row numbers.
  • Avoid chained assignment and update the original DataFrame directly.

Course illustration
Course illustration

All Rights Reserved.