Test each string in a column against a regex pattern and return a boolean validity list. By hand, call re.match(pattern, s) in a loop. With pandas, Series.str.match(pattern) applies the same match to every element and returns a boolean Series.

By hand

With pandas

.str.match(pattern) uses re.match semantics — anchored at the start, with $ anchoring the end. The same pattern r'^[A-Z]{2}\d{3}$' is used in both halves, so the results are identical.

naive.py
import re
pattern = r'^[A-Z]{2}\d{3}$'
codes = ['AB123', 'cd456', 'XY789', 'A1234', 'MN001', 'ZZ99']
result = []
for s in codes:
    result.append(re.match(pattern, s) is not None)
print('RESULT:', result)
library.py
import pandas as pd
from dalib.display import set_display
set_display()

pattern = r'^[A-Z]{2}\d{3}$'
codes = ['AB123', 'cd456', 'XY789', 'A1234', 'MN001', 'ZZ99']
df = pd.DataFrame({'x': codes})
flags = df['x'].str.match(pattern)
result = flags.tolist()
print('index:', flags.index.tolist())
print('dtype:', flags.dtype)
print('values:', flags.tolist())
print('RESULT:', result)
index: [0, 1, 2, 3, 4, 5]
dtype: bool
values: [True, False, True, False, True, False]
RESULT: [True, False, True, False, True, False]

Implementation notes

  • .str.match uses re.match (start-anchored). Without $, a string like 'AB123extra' would pass because the pattern matches the start. Include $ whenever full-string matching is required.
  • .str.fullmatch(pattern) (pandas 1.1+) anchors both ends automatically, so r'[A-Z]{2}\d{3}' without ^ or $ gives the same result.
  • re.match returns a match object or None; is not None converts it to bool in the naive half.