at[] is a scalar-only, faster specialization of loc[]: where loc[] can select whole rows, columns, or ranges depending on what you pass it, at[] can only ever get or set exactly one value, and it skips the general-purpose overhead loc[] needs to support that broader flexibility. This makes at[] the right choice specifically when you already know you're accessing a single cell by label, especially inside a loop where that overhead difference actually adds up.
1Understanding df.at[]
at[] is a scalar-only, faster specialization of loc[]: where loc[] can select whole rows, columns, or ranges depending on what you pass it, at[] can only ever get or set exactly one value, and it skips the general-purpose overhead loc[] needs to support that broader flexibility. This makes at[] the right choice specifically when you already know you're accessing a single cell by label, especially inside a loop where that overhead difference actually adds up.
Use at[] over loc[] specifically when you know you're reading or writing exactly one scalar value by label — it's measurably faster for that specific case, especially when done repeatedly in a loop, since it skips loc[]'s more general-purpose selection machinery.
import pandas as pd
df = pd.DataFrame({"score": [85, 90, 78]}, index=["a", "b", "c"])
print(df.at["b", "score"])2Practical Example
Here is a real-world application of df.at[] showing how it is used in production Pandas code.
import pandas as pd
df = pd.DataFrame({"score": [85, 90, 78]}, index=["a", "b", "c"])
df.at["c", "score"] = 100
print(df)3Best Practices
Follow these guidelines when working with df.at[]:
1. Use at[] instead of loc[] for single-scalar access/assignment when performance matters, such as inside a loop
2. Use loc[] instead of at[] whenever you might select more than a single value, a whole row, column, or range
3. Use iat[] instead of at[] when you're accessing by integer position rather than by label
Tip: Use at[] over loc[] specifically when you know you're reading or writing exactly one scalar value by label — it's measurably faster for that specific case, especially when done repeatedly in a loop, since it skips loc[]'s more general-purpose selection machinery.
import pandas as pd
df = pd.DataFrame({"score": [85, 90, 78]}, index=["a", "b", "c"])
print(df.at["b", "score"])