Pandas query
Query
pandas 는 .query() 함수를 통해 질의 형식으로 조건을 통한 데이터 필터링이 가능하다.
가독성과 편의성이 좋아 자주 사용 되지만 loc나 iloc에 비해 속도가 느리다는 단점이 있다.
기본적으로 포함된 기능은 다음과 같다.
- 비교 연산자
- in 연산자
- 논리 연산자
- 외부 변수, 함수 참조 연산
- 인덱스 검색
- 문자열 부분 검색
학습용 데이터 셋을 만들고 함수를 사용하면서 알아보자.
import pandas as pd
import numpy as np
list1 = ['정호','노제','노제','윈터','정호','노제','윈터','정호','노제','윈터','정호']
list2 = ['11/25','11/25','11/25','11/25','11/26','11/27','11/27','11/28','11/28','11/28','11/29']
list3 = ['아이폰','갤럭시','갤럭시','에어팟','에어팟','갤럭시','에어팟','아이폰','갤럭시','아이폰','에어팟']
list4 = [1,2,1,3,2,1,1,2,4,3,4]
df= pd.DataFrame({'판매원' : list1 , '판매날짜':list2 , '판매물품':list3, '판매개수':list4 })
df
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
0 | 정호 | 11/25 | 아이폰 | 1 |
1 | 노제 | 11/25 | 갤럭시 | 2 |
2 | 노제 | 11/25 | 갤럭시 | 1 |
3 | 윈터 | 11/25 | 에어팟 | 3 |
4 | 정호 | 11/26 | 에어팟 | 2 |
5 | 노제 | 11/27 | 갤럭시 | 1 |
6 | 윈터 | 11/27 | 에어팟 | 1 |
7 | 정호 | 11/28 | 아이폰 | 2 |
8 | 노제 | 11/28 | 갤럭시 | 4 |
9 | 윈터 | 11/28 | 아이폰 | 3 |
10 | 정호 | 11/29 | 에어팟 | 4 |
이번 포스팅에도 어김없이 저번에 만든 데이터를 재활용한다.
비교 연산자
우리가 가장 자주 쓰는 연산자인 비교 연산자 (==,>,>=,!=) 을 통해 데이터를 필터링 할 수 있다.
df.query("판매개수 == 2")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
1 | 노제 | 11/25 | 갤럭시 | 2 |
4 | 정호 | 11/26 | 에어팟 | 2 |
7 | 정호 | 11/28 | 아이폰 | 2 |
df.query("판매개수 >= 2")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
1 | 노제 | 11/25 | 갤럭시 | 2 |
3 | 윈터 | 11/25 | 에어팟 | 3 |
4 | 정호 | 11/26 | 에어팟 | 2 |
7 | 정호 | 11/28 | 아이폰 | 2 |
8 | 노제 | 11/28 | 갤럭시 | 4 |
9 | 윈터 | 11/28 | 아이폰 | 3 |
10 | 정호 | 11/29 | 에어팟 | 4 |
df.query("판매원 == '노제'")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
1 | 노제 | 11/25 | 갤럭시 | 2 |
2 | 노제 | 11/25 | 갤럭시 | 1 |
5 | 노제 | 11/27 | 갤럭시 | 1 |
8 | 노제 | 11/28 | 갤럭시 | 4 |
” “ 안에 원하는 조건을 작성한다.
따로 칼럼명을 따옴표로 표시할 필요는 없으나, 비교할 값이 문자열일 경우엔 해당 문자열에 작은 따옴표로 표시하여야 한다.
in 연산자
칼럼에 리스트or튜플의 값이 하나라도 존재하면 참,아니라면 거짓으로 데이터를 추출한다.
in 과 not in 을 사용하는데 이는 곧 == , != 와 같은 의미이다.
df.query("판매개수 in [1,4]")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
0 | 정호 | 11/25 | 아이폰 | 1 |
2 | 노제 | 11/25 | 갤럭시 | 1 |
5 | 노제 | 11/27 | 갤럭시 | 1 |
6 | 윈터 | 11/27 | 에어팟 | 1 |
8 | 노제 | 11/28 | 갤럭시 | 4 |
10 | 정호 | 11/29 | 에어팟 | 4 |
df.query("판매원 != ['정호','윈터']")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
1 | 노제 | 11/25 | 갤럭시 | 2 |
2 | 노제 | 11/25 | 갤럭시 | 1 |
5 | 노제 | 11/27 | 갤럭시 | 1 |
8 | 노제 | 11/28 | 갤럭시 | 4 |
논리 연산자
and, or, not 을 사용해 논리 연산이 가능하다.
true and true = true
true and false = false
true or false = true
false or false = false
주의할 점은 모두 소문자를 사용해야 한다.
df.query("(판매개수 in [1,4]) and (판매원 != ['정호','윈터'])")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
2 | 노제 | 11/25 | 갤럭시 | 1 |
5 | 노제 | 11/27 | 갤럭시 | 1 |
8 | 노제 | 11/28 | 갤럭시 | 4 |
df.query("(판매개수 in [1,4]) and not (판매원 != ['정호','윈터'])")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
0 | 정호 | 11/25 | 아이폰 | 1 |
6 | 윈터 | 11/27 | 에어팟 | 1 |
10 | 정호 | 11/29 | 에어팟 | 4 |
외부 변수, 함수 참조 연산
쿼리문을 날리는 dataframe 외부의 변수나 함수를 조건 값으로 하여 연산할 수 있다.
중요한 점은 외부 변수명과 함수명 앞에 필수적으로 @ 를 붙여 사용해야 한다.
x = 3
df.query("판매개수 == @x")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
3 | 윈터 | 11/25 | 에어팟 | 3 |
9 | 윈터 | 11/28 | 아이폰 | 3 |
def sum(x,y):
return x+y
df.query("판매개수 == @sum(1,2)")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
3 | 윈터 | 11/25 | 에어팟 | 3 |
9 | 윈터 | 11/28 | 아이폰 | 3 |
인덱스 검색
index를 통해 데이터를 필터링할 수 있다.
만약 index에 이름이 존재한다면 이름으로도 검색이 가능하다.
index명과 칼럼명이 겹쳤을 땐 칼럼을 기준으로 검색한다.
df.query("(index >=3 ) and (index <= 7)")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
3 | 윈터 | 11/25 | 에어팟 | 3 |
4 | 정호 | 11/26 | 에어팟 | 2 |
5 | 노제 | 11/27 | 갤럭시 | 1 |
6 | 윈터 | 11/27 | 에어팟 | 1 |
7 | 정호 | 11/28 | 아이폰 | 2 |
df.index.name = '인덱스'
df.query("(인덱스 >=4 ) and (인덱스 <= 6)")
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
인덱스 | ||||
4 | 정호 | 11/26 | 에어팟 | 2 |
5 | 노제 | 11/27 | 갤럭시 | 1 |
6 | 윈터 | 11/27 | 에어팟 | 1 |
문자열 부분검색
str.contains, str.startswith, str.endswith 3가지 문을 통해 문자열을 검색 할 수 있다.
str.contains()
괄호안에 문자열이 포함된 값을 검색한다.
df.query("판매원.str.contains('정')",engine='python')
판매원 | 판매날짜 | 판매물품 | 판매개수 | |
---|---|---|---|---|
인덱스 | ||||
0 | 정호 | 11/25 | 아이폰 | 1 |
4 | 정호 | 11/26 | 에어팟 | 2 |
7 | 정호 | 11/28 | 아이폰 | 2 |
10 | 정호 | 11/29 | 에어팟 | 4 |
위의 engine=’python’ 설정을 안 해준다면 쿼리문을 해석하는 엔진의 기본 값이 ‘numexpr’ 로 되어있는데 이 엔진은 문자열 검색함수를 해석하지 못 한다.
df['temp']= ['Good','Python','good','Python','good','Good','Python','good','Good','good','Good']
df.query("temp.str.contains('G')",engine='python')
판매원 | 판매날짜 | 판매물품 | 판매개수 | temp | |
---|---|---|---|---|---|
인덱스 | |||||
0 | 정호 | 11/25 | 아이폰 | 1 | Good |
5 | 노제 | 11/27 | 갤럭시 | 1 | Good |
8 | 노제 | 11/28 | 갤럭시 | 4 | Good |
10 | 정호 | 11/29 | 에어팟 | 4 | Good |
df.query("temp.str.contains('G',case=False)",engine='python')
판매원 | 판매날짜 | 판매물품 | 판매개수 | temp | |
---|---|---|---|---|---|
인덱스 | |||||
0 | 정호 | 11/25 | 아이폰 | 1 | Good |
2 | 노제 | 11/25 | 갤럭시 | 1 | good |
4 | 정호 | 11/26 | 에어팟 | 2 | good |
5 | 노제 | 11/27 | 갤럭시 | 1 | Good |
7 | 정호 | 11/28 | 아이폰 | 2 | good |
8 | 노제 | 11/28 | 갤럭시 | 4 | Good |
9 | 윈터 | 11/28 | 아이폰 | 3 | good |
10 | 정호 | 11/29 | 에어팟 | 4 | Good |
case=False 를 contains()의 파라미터 값으로 넣어주면 대소문자 구분 없이 검색해준다.
str.startswith()
특정 문자열로 시작하는 값을 찾을 수 있다.
df.query("temp.str.startswith('P')",engine='python')
판매원 | 판매날짜 | 판매물품 | 판매개수 | temp | |
---|---|---|---|---|---|
인덱스 | |||||
1 | 노제 | 11/25 | 갤럭시 | 2 | Python |
3 | 윈터 | 11/25 | 에어팟 | 3 | Python |
6 | 윈터 | 11/27 | 에어팟 | 1 | Python |
str.endswith()
특정 문자열로 끝나는 값을 찾을 수 있다.
df.query("temp.str.endswith('d')",engine='python')
판매원 | 판매날짜 | 판매물품 | 판매개수 | temp | |
---|---|---|---|---|---|
인덱스 | |||||
0 | 정호 | 11/25 | 아이폰 | 1 | Good |
2 | 노제 | 11/25 | 갤럭시 | 1 | good |
4 | 정호 | 11/26 | 에어팟 | 2 | good |
5 | 노제 | 11/27 | 갤럭시 | 1 | Good |
7 | 정호 | 11/28 | 아이폰 | 2 | good |
8 | 노제 | 11/28 | 갤럭시 | 4 | Good |
9 | 윈터 | 11/28 | 아이폰 | 3 | good |
10 | 정호 | 11/29 | 에어팟 | 4 | Good |
댓글남기기