The operations that cover most day-to-day dataframe work
A working reference for selection, cleaning, grouping and reshaping — the four things almost every pandas session is made of.
| Expression | Returns |
|---|---|
df["col"] |
One column as a Series |
df[["a", "b"]] |
Several columns as a DataFrame |
df.loc[rows, cols] |
By LABEL — the end of a slice is included |
df.iloc[0:5, 0:3] |
By POSITION — the end is excluded |
df[df["age"] > 30] |
Boolean mask |
df.query("age > 30 and city == 'Oslo'") |
The same, readably |
df.loc[df["a"] > 1, "b"] = 0 |
The assignment form that is always safe |
| Expression | Does |
|---|---|
df.isna().sum() |
Count missing values per column |
df.dropna(subset=["a"]) |
Drop rows missing a specific column |
df.fillna({"a": 0}) |
Fill per column, not globally |
df.drop_duplicates(subset=["id"], keep="last") |
De-duplicate on a key |
df.groupby("k").agg(n=("x", "size"), avg=("x", "mean")) |
Named aggregations — readable output columns |
df.merge(other, on="id", how="left", indicator=True) |
Join; _merge shows what matched |
df.pivot_table(index="a", columns="b", values="v", aggfunc="sum") |
Reshape wide |
Named aggregations give readable output columns; rank() then orders inside each group.
import pandas as pd
summary = (
df.groupby('category')
.agg(
n=('price', 'size'),
avg_price=('price', 'mean'),
top_price=('price', 'max'),
)
.reset_index()
)
# Rank WITHIN each category, best first
df['rank'] = (
df.groupby('category')['price']
.rank(method='dense', ascending=False)
.astype(int)
)
# Safe conditional assignment — one .loc, never chained indexing
df.loc[df['price'] > 100, 'tier'] = 'premium'
Chained indexing — df[mask]["col"] = value — where pandas cannot tell whether you are writing to the original frame or a temporary copy. Write it as one .loc call instead.
loc for labels, iloc for positions. The trap is that loc INCLUDES the end of a slice while iloc excludes it, exactly like the rest of Python.