Keep rows whose category field appears in an allowed-values list by testing cat in allowed for each record in a loop. With pandas, df['cat'].isin(allowed) tests membership elementwise and returns a boolean Series, replacing a chain of == comparisons with a single readable call.

By hand

With pandas

df['cat'].isin(allowed) produces a boolean Series — True where the column value is in allowed, False elsewhere. Indexing the DataFrame with it keeps only the matching rows.

naive.py
# trace: ignore records
records = [
    {'name': 'al', 'cat': 'A'},
    {'name': 'bo', 'cat': 'B'},
    {'name': 'cy', 'cat': 'A'},
    {'name': 'di', 'cat': 'C'},
]
allowed = ['A', 'C']
names = []
for r in records:
    if r['cat'] in allowed:
        names.append(r['name'])
print('RESULT:', names)
library.py
import pandas as pd
from dalib.display import set_display
set_display()

records = [
    {'name': 'al', 'cat': 'A'},
    {'name': 'bo', 'cat': 'B'},
    {'name': 'cy', 'cat': 'A'},
    {'name': 'di', 'cat': 'C'},
]
allowed = ['A', 'C']
df = pd.DataFrame(records)
mask = df['cat'].isin(allowed)
filtered = df[mask]
print('mask:', mask.tolist())
print('names:', filtered['name'].tolist())
print('shape:', filtered.shape)
print('RESULT:', filtered['name'].tolist())
mask: [True, False, True, True]
names: ['al', 'cy', 'di']
shape: (3, 2)
RESULT: ['al', 'cy', 'di']

Implementation notes

  • .isin(values) accepts any iterable — list, set, or another Series. Pandas converts the input to an internal lookup structure regardless, so the choice of list vs set does not affect .isin performance. (In the naive loop, using a set for allowed would make each in test O(1) instead of O(n) — that speedup belongs to the pure-Python half, not to pandas.)
  • The alternative (df['cat'] == 'A') | (df['cat'] == 'C') is equivalent but verbose; .isin scales cleanly to any number of allowed values.
  • To exclude a set of values instead of including them, negate the mask: df[~df['cat'].isin(excluded)]. The ~ operator inverts a boolean Series elementwise.