본문으로 건너뛰기
김신건의 로그

[Pandas] query / eval

· 수정 · 📖 약 1분 · 344자/단어 #python #pandas #selection #query
Pandas query, Pandas eval, DataFrame.query, pandas 문자열 필터

정의

  • DataFrame.query(expr) : 문자열로 boolean 표현식 을 전달해 행 필터링
  • DataFrame.eval(expr) : 문자열로 계산 표현식 을 평가

Pandas Boolean Indexing 의 가독성 있는 대안.

query 기본

df.query('age > 30')

# 동등 의미
df[df['age'] > 30]

긴 조건일수록 query 가 짧고 읽기 쉽다.

python
import pandas as pd
df = 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   city
2  Charlie   35  Seoul
nameagecity
2Charlie35Seoul

외부 변수 참조 (@)

@ 로 Python 변수를 query 안에 끌어온다.

python
min_age = 27
cities = ['Seoul', 'Busan']
result = df.query("age > @min_age and city in @cities")
print(result)
결과
      name  age   city
1      Bob   30  Busan
2  Charlie   35  Seoul

컬럼명에 공백/특수문자

# 컬럼명에 공백이 있으면 backtick
df.query('`first name` == "Alice"')
df.query('`age (years)` > 30')

연산자

연산자의미
==, !=, <, >, <=, >=비교
and, or, not논리 (&, |, ~ 도 가능)
in, not in포함
~NOT (boolean)
df.query("city in ['Seoul', 'Busan']")
df.query("not (age < 30)")

eval 로 계산

df.eval('total = price * qty')                # 새 컬럼 추가
df = df.eval('discount = price * 0.1', inplace=False)
df.eval('a + b - c')                          # Series 반환

대규모 DataFrame 에서 numexpr 기반 가속이 이뤄질 수 있다 (자동 감지).

query 의 장단점

장점

  • 가독성 : 긴 조건일수록 깔끔
  • DataFrame 이름 반복 없음
  • numexpr 가속 : 큰 DataFrame 에서 boolean indexing 보다 빠를 수 있음

단점

  • string parser 비용 : 작은 DataFrame 에는 미세하게 느림
  • 외부 함수 호출 어려움 : 람다 / 함수 호출은 boolean indexing 이 자연스러움
  • 타입 오류 시 메시지가 덜 친절

함정

1. 문자열 비교에 따옴표

df.query("name == 'Alice'")    # ✓ 안쪽 single quote
df.query('name == "Alice"')    # ✓ 안쪽 double quote
df.query('name == Alice')       # ❌ Alice 라는 컬럼 찾으려 함

2. ` (backtick) 없으면 공백 컬럼 인식 안 됨

df.query('first name == "Alice"')        # ❌
df.query('`first name` == "Alice"')      # ✓

3. &, | 의 괄호

boolean indexing 처럼 & / | 도 가능하지만 우선순위 때문에 괄호 필요.

df.query('(age > 30) & (city == "Seoul")')    # ✓
df.query('age > 30 & city == "Seoul"')         # 의도와 다른 해석 가능

and / or 가 더 안전.

참고

이 글의 용어 (3개)
[Pandas] .loc / .ilocpandas
정의 - : 라벨 기반 인덱싱 (index/column 이름) - : 정수 위치 기반 인덱싱 (0-based) 이 두 indexer 가 pandas 선택의 표준. 만으로는 헷갈리…
[Pandas] Boolean Indexingpandas
정의 Boolean Indexing 은 True/False 의 Series 를 인덱서로 전달 해 행을 선택하는 패턴. pandas 의 가장 흔한 필터링 방법. 기본 <CodeWi…
[Pandas] DataFramepandas
정의 은 2차원 레이블 테이블. 각 열이 , 모든 열이 같은 (행 라벨) 를 공유. SQL 테이블 / Excel 시트 / R data.frame 의 Python 대응체. 생성 <…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기