What is the difference between at, iat, loc and iloc in pandas?
Short answer
at and iat fetch a single cell and are faster than loc and iloc, which handle ranges and slices. Use at for a label lookup of one value and iat for a positional one.
The short version
loc and iloc select rows, columns, ranges and slices. at and iat fetch exactly one cell, and are faster because they skip all the machinery for handling ranges. Use at for a single value by label and iat for a single value by position.
The four together
import pandas as pd
df = pd.DataFrame({"city": ["Leeds", "Bath"], "amount": [5, 7]})
df.at[0, "amount"] # 5 , one cell, by label
df.iat[0, 1] # 5 , one cell, by position
df.loc[0, "amount"] # 5 , also works, but more general
df.iloc[0, 1] # 5 , also works, but more general
For a single cell, all four give the same answer. The difference is speed and intent.
Why at and iat are faster
loc and iloc must handle the possibility of a slice, a list, a boolean mask or a range, so they carry overhead even when you only want one value. at and iat accept nothing but a single row and column, so they take a much shorter path. Inside a loop over many individual lookups, the difference is noticeable.
When it actually matters
For a handful of lookups, use whatever reads best; the speed difference is irrelevant. at and iat earn their place inside a loop that touches individual cells many times, which is exactly the situation where you should first ask whether you can vectorise instead. If you can, do that: even the fastest cell access is far slower than an operation on a whole column.
Setting a single value
Both work for assignment as well as reading, and are the fastest way to poke one value.
df.at[0, "amount"] = 10
This writes to the frame directly, and being a single-cell operation it avoids the chained-assignment ambiguity that causes SettingWithCopyWarning.
The strictness of at
at only accepts a label that exists and a single column name. Passing a list, a slice or a missing label raises, which is a feature: it catches at once the mistake of thinking you are fetching one thing when you are actually fetching several.
The mnemonic
The i prefix means integer position, in both iloc and iat, exactly as it does elsewhere in pandas. So at is to loc what iat is to iloc: the same addressing scheme, restricted to a single cell.
The advice in one line
Reach for loc by default, because it is the most readable and general. Use at or iat when you are fetching or setting one cell and the speed matters. And if you find yourself using them in a big loop, stop and ask whether a vectorised expression would replace the loop entirely.