Select rows and columns by label — and, most often, by a condition.
.loc is how you say "the rows where this is true" and "these columns, by name". It is also the piece that makes method chaining work, because .loc accepts a deferred expression, letting you filter a data frame that has no name yet.
Official documentation: DataFrame.loc
The forms worth knowing
df.loc['Japan'] # one row, by index label
df.loc['Japan', 'Capacity (MW)'] # one cell: row label, column label
df.loc[:, ['Country', 'Status']] # all rows, two columns by name
df.loc[pd.col('mag') > 7] # boolean condition
df.loc[pd.col('mag') > 7, 'place'] # condition, and one column
df.loc['a':'c'] # label slice -- 'c' IS included
That last one catches people: unlike ordinary Python slicing, a .loc slice includes its endpoint, because you are naming labels rather than counting positions.
pd.col, and why it matters
Inside a chain, the intermediate data frame has no variable name — so you cannot write df[df['x'] > 5], because there is no df to refer to. pd.col, introduced in Pandas 3.0, solves this: it is a deferred reference to a column, resolved against whatever the chain has produced at that point.
(
df
.loc[pd.col('Available Globally?') == 'Yes']
.loc[pd.col('Hours Viewed') > 500_000_000]
)
Each .loc filters what the previous one produced, so conditions stack readably rather than piling into one enormous boolean expression. pd.col works wherever a column reference makes sense — including inside assign:
df.assign(hours_millions=pd.col('Hours Viewed') / 1_000_000)
Conditions combine with & and |, each side parenthesized, and the usual methods are available:
df.loc[(pd.col('mag') > 7) & (pd.col('depth') < 50)]
df.loc[pd.col('Region').isin(['Asia', 'Europe'])]
A note on older code
Before Pandas 3.0 the same job was done with a lambda, which .loc also accepts:
df.loc[lambda df_: df_['Hours Viewed'] > 500_000_000]
The df_ name was a convention meaning "the frame at this point in the chain". You will see this form throughout the older Bamboo Weekly archive, and it still works — but pd.col says the same thing with less ceremony, and is the form to reach for in new code.
If you are reading older code and want the lambda form explained properly, see Selecting rows in Pandas using .loc and lambda.
A worked example, on real data
Netflix published an engagement report listing every title watched over six months, with hours viewed and whether it was available worldwide. Bamboo Weekly #45 used it.
The question: which globally available titles passed 500 million hours viewed?
import pandas as pd
url = ('https://www.bambooweekly.com/content/files/4cd45et68cgf/1HyknFM84ISQpeua6TjM7A/'
'97a0a393098937a8f29c9d29c48dbfa8/'
'what_we_watched_a_netflix_engagement_report_2023jan-jun.xlsx')
(
pd.read_excel(url, skiprows=5,
usecols=['Title', 'Available Globally?', 'Release Date', 'Hours Viewed'])
.loc[pd.col('Available Globally?') == 'Yes']
.loc[pd.col('Hours Viewed') > 500_000_000]
.sort_values('Hours Viewed', ascending=False)
.head(5)
)
Which gives:
Title Available Globally? Release Date Hours Viewed
The Night Agent: Season 1 Yes 2023-03-23 812100000
Ginny & Georgia: Season 2 Yes 2023-01-05 665100000
The Glory: Season 1 // 더 글로리: 시즌 1 Yes 2022-12-30 622800000
Wednesday: Season 1 Yes 2022-11-23 507700000
Queen Charlotte: A Bridgerton S... Yes 2023-05-04 503000000
Five rows out of 18,214, with no intermediate variables and each filtering step readable on its own line.
Three mistakes people make
Chained indexing, which in Pandas 3.0 silently does nothing. Writing df[df['a'] > 1]['b'] = 99 raises a ChainedAssignmentError warning and leaves your data frame completely unchanged — the assignment lands on a temporary object that is discarded. This is the single most dangerous habit in Pandas, because your code appears to run. Say it in one .loc instead:
df.loc[pd.col('a') > 1, 'b'] = 99
This is the Pandas 3 behavior of copy-on-write, which replaced the old SettingWithCopyWarning. I explain what changed and why in SettingWithCopyWarning? Not in Pandas 3, thanks to "copy on write".
Confusing .loc with .iloc. .loc uses labels, .iloc uses integer positions. They coincide on a default RangeIndex, which lets the confusion survive until the day you sort or filter and the labels stop matching the positions.
Assuming a .loc slice stops before the endpoint. df.loc['a':'c'] returns a, b and c. Python slicing excludes the end; label-based slicing includes it, since Pandas cannot know what comes "just before" a label. I demonstrate both of those last two in How .loc and .iloc treat Pandas slices differently. And on why the syntax is square brackets rather than parentheses: Why we call .loc with [] and not ().
Practice it
Work through a .loc exercise, with instant feedback and no signup required: practice.lernerpython.com/bamboo-weekly/loc/
Go deeper
Bamboo Weekly is the practice. If you want the structured version — full courses with downloadable Jupyter notebooks, plus live Pandas office hours when you get stuck — that is LernerPython+Data. A paid Bamboo Weekly subscription is included with it.
See it on real data
Below are the 159 Bamboo Weekly exercises that use loc on real-world data — try each one, then study the worked solution.
- Bamboo Weekly #182: Surveillance technology
- Bamboo Weekly #181: Housing costs
- Bamboo Weekly #179: Krakow tourism
- Bamboo Weekly #178: Harmful algal bloom
- Bamboo Weekly #177: European Summer
- Bamboo Weekly #176: Religious restrictions
- Bamboo Weekly #175: Inflation
- Bamboo Weekly #174: Vacation
- Bamboo Weekly #173: IPOs
- Bamboo Weekly #172: World Cup
- Bamboo Weekly #171: Hantavirus
- Bamboo Weekly #170: Port of Long Beach
- Bamboo Weekly #169: Press freedom
- Bamboo Weekly #167: Oil prices
- Bamboo Weekly #166: Income tax
- Bamboo Weekly #164: Fertilizer
- Bamboo Weekly #163: Daylight saving time
- Bamboo Weekly #162: Spotify and car accidents
- Bamboo Weekly #161: Missiles in Israel
- Bamboo Weekly #160: Strait of Hormuz
- Bamboo Weekly #159: State of the Union
- Bamboo Weekly #157: Government corruption
- Bamboo Weekly #156: Winter Olympics
- Bamboo Weekly #155: Gold
- Bamboo Weekly #154: University rankings
- Bamboo Weekly #153: Venezuela
- Bamboo Weekly #152: Congestion pricing
- Bamboo Weekly #150: Kalshi
- Bamboo Weekly #149: Flu season
- Bamboo Weekly #148: US Manufacturing
- Bamboo Weekly #147: Presidential pardons
- Bamboo Weekly #146: Thanksgiving travel
- Bamboo Weekly #145: Economic indicators
- Bamboo Weekly #144: Museum Heists
- Bamboo Weekly #143: Phones in school
- Bamboo Weekly #142: Hurricanes
- Bamboo Weekly #141: Argentina
- Bamboo Weekly #140: Stack Overflow survey
- Bamboo Weekly #139: Chinese exports
- Bamboo Weekly #138: Federal workers
- Bamboo Weekly #137: UN Security Council
- Bamboo Weekly #136: Indian vehicles
- Bamboo Weekly #135: Airline seats
- Bamboo Weekly #134: Taiwan weather
- Bamboo Weekly #133: Wind power
- Bamboo Weekly #131: Canadian border crossings
- Bamboo Weekly #130: Jobs reporting
- Bamboo Weekly #129: Tom Lehrer
- Bamboo Weekly #126: EV sales
- Bamboo Weekly #125: Shrinking dollars
- Bamboo Weekly #124: NATO Spending
- Bamboo Weekly #123: Missiles
- Bamboo Weekly #122: Economic growth
- Bamboo Weekly #121: Research funding
- Bamboo Weekly #120: Pennies
- Bamboo Weekly #119: Python conferences
- Bamboo Weekly #118: Flight delays
- Bamboo Weekly #117: Electricity
- Bamboo Weekly #116: Philadelphia Fed survey
- Bamboo Weekly #115: Sahm rule
- Bamboo Weekly #114: International trade
- Bamboo Weekly #113: US airport traffic
- Bamboo Weekly #112: Programming jobs
- Bamboo Weekly #111: State taxes
- Bamboo Weekly #110: Credit access
- Bamboo Weekly #109: Cacao nibs
- Bamboo Weekly #108: Measles
- Bamboo Weekly #107: Consumer confidence
- Bamboo Weekly #106: Flu season
- Bamboo Weekly #105: Federal employees
- Bamboo Weekly #104: Aviation accidents
- Bamboo Weekly #103: CDC data
- Bamboo Weekly #102: WordPress
- Bamboo Weekly #101: Los Angeles Fires
- Bamboo Weekly #100: Sports betting
- Bamboo Weekly #99: Literacy and numeracy
- Bamboo Weekly #96: Taylor Swift
- Bamboo Weekly #95: Tariffs
- Bamboo Weekly #94: Strategic Wine Reserve
- Bamboo Weekly #93: Anti-politics
- Bamboo Weekly #92: Climate disaster costs
- Bamboo Weekly #91: Roller coasters
- Bamboo Weekly #90: Voter participation
- Bamboo Weekly #88: Hot summers
- Bamboo Weekly #87: Nuclear power
- Bamboo Weekly #86: FEMA
- Bamboo Weekly #85: PACs and parties
- Bamboo Weekly #84: Central banks
- Bamboo Weekly #83: Gasoline prices
- Bamboo Weekly #82: Broadband
- Bamboo Weekly #81: School
- Bamboo Weekly #79: Cyber attacks
- Bamboo Weekly #77: Paris Olympics
- Bamboo Weekly #76: Aging legislators
- Bamboo Weekly #75: Refugees
- Bamboo Weekly #74: UK elections
- Bamboo Weekly #73: Avocado hand
- Bamboo Weekly #72: City travel
- Bamboo Weekly #71: Holidays
- Bamboo Weekly #70: Moon missions
- Bamboo Weekly #69: Election participation
- Bamboo Weekly #67: Electric cars
- Bamboo Weekly #65: Microplastics
- Bamboo Weekly #64: Coal power
- Bamboo Weekly #63: Ukraine aid
- Bamboo Weekly #62: Economic report card
- Bamboo Weekly #61: Solar eclipse
- Bamboo Weekly #60: Iceland
- Bamboo Weekly #59: Long covid
- Bamboo Weekly #57: International arms trade
- Bamboo Weekly #56: Rent increases
- Bamboo Weekly #55: IVF
- Bamboo Weekly #53: Airport animals
- Bamboo Weekly #52: Border encounters
- Bamboo Weekly #51: Academy Awards
- Bamboo Weekly #50: Red Sea shipping
- Bamboo Weekly #49: Campaign finance
- Bamboo Weekly #48: Aviation accidents
- Bamboo Weekly #47: Minimum wage
- Bamboo Weekly #46: Pedestrians
- Bamboo Weekly #45: Netflix
- Bamboo Weekly #44: Global economics
- Bamboo Weekly #43: Financial protection
- Bamboo Weekly #42: Plant hardiness
- Bamboo Weekly #41: Wine production
- Bamboo Weekly #40: Sovereign Bonds
- Bamboo Weekly #39: WeWork
- Bamboo Weekly #37: Consumer finances
- Bamboo Weekly #36: Nobel Prize
- Bamboo Weekly #35: Terrorism
- Bamboo Weekly #34: House of Representatives
- Bamboo Weekly #33: Fracking
- Bamboo Weekly #32: Unions
- Bamboo Weekly #31: Poverty
- Bamboo Weekly #30: Uncertainty
- Bamboo Weekly #29: Auto accidents
- Bamboo Weekly #28: Pret a Manger
- Bamboo Weekly #27: Young voters
- Bamboo Weekly #26: Hot weather
- Bamboo Weekly #25: Entrepreneurship
- Bamboo Weekly #24: Wildfire smoke
- Bamboo Weekly #22: Banana index
- Bamboo Weekly #21: Electric cars
- Bamboo Weekly #20: World inflation
- Bamboo Weekly #19: Working women
- Bamboo Weekly #18: World population
- Bamboo Weekly #16: Consumer oil prices
- Bamboo Weekly #15: Eurovision
- Bamboo Weekly #14: JOLTS
- Bamboo Weekly #13: Python developers
- Bamboo Weekly #12: Tourism
- Bamboo Weekly #11: Software jobs
- Bamboo Weekly #10: Oil prices
- Bamboo Weekly #9: US house prices
- Bamboo Weekly #8: Happiness
- Bamboo Weekly #7: Bank failures
- Bamboo Weekly #6: End of the humanities?
- Bamboo Weekly #4: Eating well
- Bamboo Weekly #3: Earthquake
Part of the Pandas Methods Index. See also practice by skill.