Boolean masks
df[df['revenue'] > 1000]
df[df['region'] == 'East']
df[df['region'].isin(['East', 'West'])]
df[df['name'].str.contains('Ltd', na=False)]
The expression inside the brackets produces True/False per row; pandas keeps the True ones.
Combining conditions
Use & and |, and parenthesise everything
pandas needs & and |, not and and or. And because & binds tighter than >, every condition needs its own parentheses.
Raises ValueError
df[df['a'] > 1 and df['b'] < 5]
df[df['a'] > 1 & df['b'] < 5]Correct
df[(df['a'] > 1) & (df['b'] < 5)]The error message — truth value of a Series is ambiguous — is confusing the first time. It means you used and where & was required.
loc and iloc
df.loc[df['revenue'] > 1000, 'region'] # by label / condition
df.loc[df['revenue'] > 1000, ['region', 'revenue']]
df.iloc[0:5, 0:3] # by position
loc works with labels and boolean masks. iloc works with integer positions. loc includes the end of a slice; iloc excludes it, matching normal Python slicing.
query()
df.query('revenue > 1000 and region == "East"')
More readable for long filters, and and is allowed here because the string is parsed separately. Slightly slower, and it cannot handle column names with spaces without backticks.