정규 표현식으로 패턴 찾기
정규 표현식을 사용해 .str.extract(), .str.contains(), .str.match()로 부분 문자열을 추출하고 패턴을 확인합니다.
정규 표현식으로 패턴 찾기은(는) CoddyKit의 무료 Pandas & NumPy Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Pandas & NumPy Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
Pandas에서 정규식을 사용하는 이유
정규 표현식(정규식)은 문자열 패턴을 설명하는 언어입니다. Pandas에서는 .str 접근자를 통해 contains(), match(), extract(), findall(), replace()에서 정규식을 사용할 수 있습니다. 단순한 contains/startswith 확인으로는 처리하기에 패턴이 너무 복잡할 때 정규식이 적합합니다. 예를 들어 이메일 형식 검증, 자유 형식 텍스트에서 전화번호 추출, 메모 열에서 모든 달러 금액 찾기 등에 사용할 수 있습니다.
import pandas as pd
df = pd.DataFrame({
'text': ['Order #12345 placed', 'No order', 'Ref #67890 paid', 'Refund for #11111']
})
# Find rows that contain an order number (# followed by 5 digits)
has_order = df['text'].str.contains(r'#\d{5}', regex=True)
print(df[has_order])
# text
# 0 Order #12345 placed
# 2 Ref #67890 paid
# 3 Refund for #11111.str.contains()와 정규식
regex=True(기본값)인 .str.contains(pattern)은 문자열의 어느 위치에서든 패턴이 일치하는 곳에 True를 반환하는 불리언 Series를 만듭니다. 일치가 발생할 위치를 제한하려면 ^(시작)와 $(끝) 같은 앵커를 사용하세요. 일반적인 용도는 유효한 날짜 패턴이나 올바른 형식의 코드처럼 필드가 형식 요구 사항과 일치하는 행을 필터링하는 것입니다.
import pandas as pd
df = pd.DataFrame({
'code': ['US-001', 'UK-042', 'DE-18', 'FR-', 'us-003']
})
# Valid format: two uppercase letters, hyphen, 3 digits
valid = df['code'].str.contains(r'^[A-Z]{2}-\d{3}$', regex=True)
print(df['code'][valid].tolist())
# ['US-001', 'UK-042'].str.match()로 시작 위치부터 일치시키기
.str.match(pattern)은 각 문자열이 패턴으로 시작하는지 확인합니다(패턴이 문자열의 시작 부분에 고정됩니다). 이는 문자열의 어느 위치에서나 검색하는 contains()와의 차이입니다. 문자열의 접두사만 관심이 있을 때는 match()를 사용하고, 문자열 전체가 패턴과 일치해야 할 때는 fullmatch()를 사용하세요.
import pandas as pd
df = pd.DataFrame({'id': ['ORD001', 'ORD002', 'RET003', 'ORDXYZ']})
# Match rows whose ID starts with 'ORD' followed by digits
orders = df['id'].str.match(r'ORD\d+')
print(df[orders])
# id
# 0 ORD001
# 1 ORD002
# match() is anchored at start, so 'ORDXYZ' (XYZ not digits) is excluded.str.extract()로 캡처 그룹 추출하기
.str.extract(pattern)은 정규식 패턴에서 () 캡처 그룹을 사용하여 일치하는 문자열의 특정 부분을 가져옵니다. 캡처 그룹마다 하나의 열이 있는 DataFrame을 반환합니다. 각 문자열에서 첫 번째 일치 항목만 반환됩니다. 자유 형식 텍스트에 포함된 숫자 값, 날짜, ID와 같은 구조화된 데이터를 추출할 때 특히 적합합니다.
import pandas as pd
df = pd.DataFrame({
'notes': ['Shipped on 2024-01-15', 'Delivered on 2024-03-20', 'Pending', 'Shipped on 2024-07-04']
})
# Extract the date (YYYY-MM-DD) from the notes column
dates = df['notes'].str.extract(r'(\d{4}-\d{2}-\d{2})')
df['shipped_date'] = dates[0]
print(df[['notes', 'shipped_date']])
# notes shipped_date
# 0 Shipped on 2024-01-15 2024-01-15
# 1 Delivered on 2024-03-20 2024-03-20
# 2 Pending NaN
# 3 Shipped on 2024-07-04 2024-07-04이름이 지정된 캡처 그룹
(?P<name>...) 구문을 사용하여 캡처 그룹에 이름을 지정할 수 있습니다. str.extract()에서 이름이 지정된 그룹을 사용하면 결과 DataFrame이 해당 이름을 열 머리글로 자동 사용하므로, 나중에 열 이름을 바꾸지 않아도 결과 자체를 설명할 수 있습니다.
import pandas as pd
df = pd.DataFrame({
'entry': ['Alice (25, Engineer)', 'Bob (30, Manager)', 'Carol (28, Analyst)']
})
# Named capturing groups
extracted = df['entry'].str.extract(
r'(?P<name>\w+) \((?P<age>\d+), (?P<role>\w+)\)'
)
print(extracted)
# name age role
# 0 Alice 25 Engineer
# 1 Bob 30 Manager
# 2 Carol 28 Analyst여러 일치 항목을 위한 .str.extractall()
.str.extractall(pattern)은 각 문자열에서 패턴과 일치하는 모든 항목을 찾습니다(첫 번째 항목만 찾지 않습니다). MultiIndex가 있는 DataFrame을 반환합니다. 바깥쪽 수준은 원래 행 인덱스이고 안쪽 수준(match)은 행마다 일치 항목의 순서를 셉니다. 자유 형식 텍스트 필드에서 모든 숫자, URL 또는 키워드를 추출할 때 유용합니다.
import pandas as pd
df = pd.DataFrame({
'text': ['Call 555-1234 or 555-5678', 'Contact 800-9000', 'No numbers']
})
# Extract all phone patterns
all_phones = df['text'].str.extractall(r'(\d{3}-\d{4})')
print(all_phones)
# 0
# match
# 0 0 555-1234
# 1 555-5678
# 1 0 800-9000일치 항목 목록을 위한 .str.findall()
.str.findall(pattern)은 목록으로 이루어진 Series를 반환하며, 각 목록에는 해당 행의 문자열에서 찾은 모든 일치 항목이 들어 있습니다. extractall()과 달리 MultiIndex를 만들지 않고 각 행에 일치 항목 목록을 할당합니다. 결과를 평평한 구조로 유지하거나 행마다 일치 항목 수를 셀 때 편리합니다.
import pandas as pd
df = pd.DataFrame({
'text': ['Buy 3 items for $10 each', 'Save $5 on 2 products', 'No deal']
})
# Find all dollar amounts
df['prices'] = df['text'].str.findall(r'\$\d+')
df['price_count'] = df['prices'].str.len()
print(df[['text', 'prices', 'price_count']])
# text prices price_count
# 0 Buy 3 items for $10 each [$10] 1
# 1 Save $5 on 2 products [$5] 1
# 2 No deal [] 0re.IGNORECASE로 대소문자를 구분하지 않고 일치시키기
기본적으로 Pandas의 정규식은 대소문자를 구분합니다. flags=re.IGNORECASE(또는 re.I)를 전달하면 패턴이 대소문자를 구분하지 않게 됩니다. 따라서 'python', 'Python', 'PYTHON'을 동일하게 일치시키고 싶을 때 [Pp][Yy][Tt][Hh][Oo][Nn]과 같은 대안 패턴을 작성할 필요가 없습니다.
import pandas as pd
import re
df = pd.DataFrame({
'skill': ['Python', 'JAVA', 'javascript', 'PyThOn developer', 'SQL']
})
# Case-insensitive search for python
mask = df['skill'].str.contains('python', flags=re.IGNORECASE, regex=True)
print(df[mask])
# skill
# 0 Python
# 3 PyThOn developer전체 일치로 형식 검증하기
.str.fullmatch(pattern)(Pandas 1.1에서 추가됨)은 문자열 전체가 패턴과 일치할 때만 True를 반환합니다. 부분 문자열과 일치하는 contains()와 달리 fullmatch는 ^...$ 앵커를 사용하는 것과 같습니다. 이메일 주소, 전화번호, 우편번호처럼 엄격한 스키마를 따르는 필드의 형식 준수 여부를 검증하는 가장 안전한 방법입니다.
import pandas as pd
df = pd.DataFrame({
'email': ['alice@example.com', 'bob_at_work', 'carol@test', 'dave@org.co']
})
# Simple email validation: word@word.word
valid_email = df['email'].str.fullmatch(r'[\w.+-]+@[\w-]+\.[\w.]+')
print(df[valid_email])
# email
# 0 alice@example.com
# 3 dave@org.co정규식 역참조로 바꾸기
str.replace(pattern, repl, regex=True)를 사용할 때 교체 문자열에 r'\1'과 같은 역참조를 포함하여 첫 번째 () 그룹에 캡처된 내용을 참조할 수 있습니다. 이를 통해 날짜 형식을 MM/DD/YYYY에서 YYYY-MM-DD로 바꾸거나 일치한 단어를 HTML 태그로 감싸는 등 강력한 재구성을 수행할 수 있습니다.
import pandas as pd
df = pd.DataFrame({'phone': ['(555) 123-4567', '(800) 555-0199', '(212) 867-5309']})
# Reformat to 555-123-4567
df['phone_clean'] = df['phone'].str.replace(
r'\((\d{3})\) (\d{3})-(\d{4})',
r'\1-\2-\3',
regex=True
)
print(df)
# phone phone_clean
# 0 (555) 123-4567 555-123-4567
# 1 (800) 555-0199 800-555-0199
# 2 (212) 867-5309 212-867-5309정규식 기반 데이터 추출기 만들기
이제 이름이 지정된 그룹을 사용하여 지저분한 메모 열에서 제품 SKU와 가격을 추출하는 실용적인 전체 예를 살펴보겠습니다. 여러 필드가 하나의 텍스트 필드에 이어 붙어 있는 기존 시스템에서 데이터를 가져올 때 이러한 유형의 추출을 흔히 사용합니다.
import pandas as pd
df = pd.DataFrame({
'note': [
'SKU:A001 price:$49.99 in stock',
'SKU:B202 price:$12.50 low stock',
'No SKU available'
]
})
extracted = df['note'].str.extract(
r'SKU:(?P<sku>\w+).*price:\$(?P<price>[\d.]+)'
)
print(extracted)
# sku price
# 0 A001 49.99
# 1 B202 12.50
# 2 NaN NaN빠른 확인
Pandas에서 정규식을 사용한 패턴 일치에 대한 이해도를 확인해 보세요.
수업 요약
이번 수업에서는 다음을 배웠습니다. str.contains(regex)는 패턴으로 행을 필터링하고, str.extract()는 첫 번째 일치 항목을 DataFrame 열로 캡처합니다(결과 자체를 설명할 수 있도록 이름이 지정된 그룹을 사용하세요). str.extractall()은 MultiIndex와 함께 행마다 모든 일치 항목을 찾고, str.fullmatch()는 문자열 전체가 패턴을 따르는지 검증합니다. 다음에는 여러 텍스트 열을 결합하고 정리합니다.
자주 묻는 질문
“정규 표현식으로 패턴 찾기” 강의는 무료인가요?
네 — “정규 표현식으로 패턴 찾기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Pandas & NumPy Academy 강의 전체를 잠금 해제할 수 있습니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“정규 표현식으로 패턴 찾기”에서 뭘 배우나요?
정규 표현식을 사용해 .str.extract(), .str.contains(), .str.match()로 부분 문자열을 추출하고 패턴을 확인합니다. 브라우저에서 직접 실행하는 실습 코드로 Pandas & NumPy Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Pandas & NumPy Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Pandas & NumPy Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“정규 표현식으로 패턴 찾기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Pandas & NumPy Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Pandas & NumPy Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- .str 접근자
- 문자열 나누고 바꾸기
- 정규 표현식으로 패턴 찾기
- 텍스트 열 결합과 정리