pandas: the 8 verbs that do 90% of the work
Filter, select, sort, transform, group, aggregate, join, reshape. The pandas core in one page, with a free print-ready PDF.
Get the free PDF
One page, print-ready, free to share. No signup needed.
Most pandas tutorials teach 200 methods. Real notebooks use about eight, over and over. This sheet is those eight verbs: what they do, the variant that matters, and the one trap that silently eats your edits.
The core 8
1. Filter rows
df[df.price > 100] # boolean mask
df.query("price > 100") # same thing, reads better
2. Select columns
df[['name', 'price']] # by name
df.loc[rows, cols] # by label
df.iloc[0:5, 0:2] # by position
3. Sort
df.sort_values('price') # ascending by default
df.sort_values('price', ascending=False) # flip it
4. Transform
df.assign(tax=df.price * 0.2) # new column, chainable
df['col'].astype(int) # cast a type
5. Group
df.groupby('city') # split into groups
df.groupby('city').size() # rows per group
6. Aggregate
df.groupby('city').agg(avg=('price', 'mean')) # named result columns
df.groupby('city').agg(['min', 'max']) # several at once
7. Join
df.merge(other, on='id') # SQL INNER JOIN
df.merge(other, on='id', how='left') # SQL LEFT JOIN
8. Reshape
df.pivot_table(index='city', columns='month', values='amount') # long to wide
df.melt(id_vars='city') # wide to long
The workhorse pattern
Split, aggregate, rank. The most typed pattern in analytics:
revenue = (df
.groupby('city')
.agg(orders=('id', 'count'),
revenue=('amount', 'sum'))
.reset_index()
.sort_values('revenue', ascending=False))
Named aggregations keep your output columns readable: new_name=('col', 'fn').
merge is just SQL
df.merge is SQL joins wearing a Python coat:
# a LEFT JOIN, pandas edition
orders.merge(customers,
on='customer_id',
how='left')
# unmatched rows get NaN
how= takes inner, left, right, outer. Same semantics as SQL, and the same row fan-out trap: if the right side has 3 matching rows, your left row appears 3 times (see the SQL JOINs sheet for the full story).
The trap: the silent copy
df[df.x > 0]['y'] = 1 changes nothing, and tells you almost nothing.
# looks fine, writes into a temporary copy
df[df.x > 0]['y'] = 1
# selection + write in one step
df.loc[df.x > 0, 'y'] = 1
Chained indexing creates an intermediate object; the assignment lands on the copy. .loc does it in place.
Frequently asked questions
- What is the difference between merge and join in pandas?
- df.merge() is the general tool: it joins on any columns or indexes and takes how='inner', 'left', 'right' or 'outer', exactly like SQL joins. df.join() is a convenience wrapper that joins on the index. When in doubt, use merge.
- When should I use loc vs iloc?
- Use .loc when you select by label (column names, index values) and .iloc when you select by integer position. loc includes both ends of a slice, iloc excludes the stop, matching normal Python slicing.
- What is the difference between pivot and pivot_table?
- pivot() purely reshapes and fails if there are duplicate index/column pairs. pivot_table() aggregates duplicates with a function you choose (mean by default), so it works on messy real-world data. In practice you will use pivot_table most of the time.
- Why is chained indexing like df[df.x > 0]['y'] = 1 a problem?
- The first bracket creates a temporary copy, and the assignment writes to that copy, not to your DataFrame. Nothing changes and pandas may only give you a warning. Use df.loc[df.x > 0, 'y'] = 1, which selects and writes in a single step.
Get the free PDF
One page, print-ready, free to share. No signup needed.
