import pandas as pddf = pd.DataFrame({ 'name': ['Alice', 'Bob', 'Charlie', 'Dave'], 'age': [25, 30, 35, 40], 'city': ['Seoul', 'Busan', 'Seoul', 'Daegu'],})result = df.query("age > 27 and city == 'Seoul'")print(result)
결과
name age city2 Charlie 35 Seoul
외부 변수 참조 (@)
@ 로 Python 변수를 query 안에 끌어온다.
python
min_age = 27cities = ['Seoul', 'Busan']result = df.query("age > @min_age and city in @cities")print(result)
결과
name age city1 Bob 30 Busan2 Charlie 35 Seoul
# 함수 결과도 변수로 전달 가능threshold = df['salary'].quantile(0.9)df.query("salary >= @threshold")
연산자
연산자
의미
==, !=, <, >, <=, >=
비교
and, or, not
논리 (권장)
&, |, ~
비트 논리 (가능하지만 괄호 필요)
in, not in
포함 여부
df.query("city in ['Seoul', 'Busan']")df.query("not (age < 30)")df.query("age > 25 and city != 'Daegu'")df.query("10 < age < 40") # Python 체이닝 비교 가능 (boolean indexing 과 다름)
boolean indexing 으로 같은 코드를 쓰면 df 이름이 반복되고 중간 변수가 필요해진다.
boolean indexing 과 비교
항목
Boolean Indexing
query()
가독성
복잡 조건 시 장황
간결
성능 (소규모)
빠름
파싱 오버헤드 있음
성능 (대규모)
기본
numexpr 활용 시 더 빠름
컬럼명 제약
없음
예약어/공백 시 backtick 필요
외부 변수
직접 참조
@var 필요
복잡한 메서드
.str.contains() 등 자유
제한적
체이닝 비교
불가 (10 < age < 40)
가능
# boolean indexing 이 더 자연스러운 경우df[df['name'].str.startswith('A')]df[df['tags'].apply(lambda x: 'python' in x)]# query 가 더 자연스러운 경우df.query("10 < age < 40 and city in ['Seoul', 'Busan']")
numexpr 가속
# numexpr 설치 여부 확인import numexprprint(numexpr.__version__)# 대용량 DataFrame 에서 query 가 더 빠른 경우import pandas as pddf = pd.DataFrame({'a': range(1_000_000), 'b': range(1_000_000)})# numexpr 사용 (설치된 경우 자동)df.query("a > 500000 and b < 800000")# 엔진 명시df.query("a > 500000", engine='numexpr') # numexpr 강제df.query("a > 500000", engine='python') # Python 강제
실전 패턴
날짜 범위 필터
start = '2024-01-01'end = '2024-12-31'df.query("date >= @start and date <= @end")
여러 값 포함 필터
valid_statuses = ['active', 'pending', 'trial']df.query("status in @valid_statuses")
수치 범위 + 카테고리 복합
df.query("10 < age < 65 and department in ['eng', 'data'] and salary > 5000")
함정
1. 문자열 비교에 따옴표
df.query("name == 'Alice'") # ✓ 안쪽 single quotedf.query('name == "Alice"') # ✓ 안쪽 double quotedf.query('name == Alice') # ❌ Alice 라는 컬럼을 찾으려 함
df.query('(age > 30) & (city == "Seoul")') # ✓df.query('age > 30 & city == "Seoul"') # 의도와 다른 해석 가능# and / or 가 더 안전df.query('age > 30 and city == "Seoul"') # ✓
4. 외부 함수 호출 불가
# ❌ query 안에서 함수 호출 불가df.query("name.str.startswith('A')")# ✓ boolean indexing 사용df[df['name'].str.startswith('A')]
5. 소규모 DataFrame 에서 오버헤드
# 행이 수백 개 이하면 query 파싱 비용이 더 클 수 있음# 소규모: boolean indexing 이 빠름# 대규모 (100만+ 행): query + numexpr 가 유리
💬 댓글