파이썬 버전 3.7 기준
pandas 버전 0.25.1 기준
query 메서드 옵션, 설명, 사용 예 |
본 포스팅에서는 query 메서드의 대한 내용, 설명, 사용 예 등을 서술한다.
query 메서드 |
pandas에서 DataFrame은 query 메서드를 지원한다.
이 메서드는 조건식을 문자열로 입력받아 해당 조건에 만족하는 행을 추출해 출력해주는 함수이다.
사용 방법은 간단한데, 단순히 대괄호[ ]에서 조건식을 입력했던 것과 동일하게 입력을 해주면 되나 차이점은 문자열이 들어간다는 것이다.
query() 메서드 사용형식)
DataFrame.query(expr, inplace=False)
expr은 입력되는 조건식을 입력받는다.
○ 입력되는 조건식은 문자열로 입력받는다.
inplace가 True일 경우 query에 의해 출력된 데이터로 원본 데이터를 대체한다.
참고사항(query 메서드를 굳이 사용하는 이유?)
사실 대괄호[ ]를 사용하여 조건식을 입력해도 되는데 굳이 query 메서드를 사용하는 이유는 방대한 양의 데이터를 처리할 경우 이 메서드가 성능면에서 우위를 보여준다.
○ pandas 공식 사이트에서는 약 200,000개의 행 이상을 처리할 경우에는 이 메서드가 성능면에서 우위를 보인다고 설명한다.
○ 하지만 적은 양의 데이터를 처리할 경우 큰 차이는 보이지 않는다.
query메서드의 특징
query 메서드의 특징으로는 다음과 같다.
○ 표현식을 문자열로 입력받는다.
○ 단순하게 열의 레이블을 표현식에 넣어 사용이 가능하다.
○ index 역시 표현식에 넣어 사용이 가능하다.
○ 대용량의 데이터를 처리할 경우 대괄호 조건식을 사용하는 것 보다 성능이 좋다.
○ 비교연산자와 논리연산자 중 비교연산자가 우선순위가 있으므로 표현식이 단순해진다.
query에 적용되는 조건식의 문법 특징
조건식사용은 다음 예제와 같이 적용될 수 있다.
○ query메서드와 대괄호[ ]를 사용한 결과는 동일하다.
조건식 사용 예)
DataFrame[ (DataFrame.a < DataFrame.b) & (DataFrame.b < DataFrame.c) ]
DataFrame.query( '(a < b) & (b < c)' )
하지만 비교연산자가 논리연산자보다 우위에 있다는 점을 이용하면 이런 문법을 더욱 단순화 시킬 수 있다.
○ 먼저 위 예제에서 소괄호()를 지울 수 있다.
○ 논리연산자의 경우 심볼 대신에 영어를 사용할 수도 있다.
○ 비교연산자가 논리연산자(&와 |)보다 우선순위가 높다.
아래 예제의 ①, ②, ③은 모두 동등한 결과를 보여준다.
단순문법 사용 예)
① DataFrame.query( 'a < b & b < c' )
② DataFrame.query( 'a < b and b < c' )
③ DataFrame.query( 'a < b < c' )
query 메서드 단순 사용 예제 |
다음 예제는 c0열과 c2열 사이에 c1의 값이 존재하는 행만 추출해 출력하는 것을 보여준다.
query 메서드 사용 예)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
# 예제용 배열 선언
In[4]: ex_df=pd.DataFrame([[0,1,2], [3,4,5], [8,7,9]], index=['r0','r1','r2'], columns=['c0','c1','c2'])
In[5]: ex_df.query('c0<c1<c2')
Out[5]:
c0 c1 c2
r0 0 1 2
r1 3 4 5
index 객체로의 사용 예제 |
입력된 이름을 가진 열이 없고 인덱스의 이름과 일치할 경우 인덱스 객체로 동일한 작업을 수행한다.
index 객체로의 query 메서드 사용 예 1)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
# 예제용 배열 선언 및 인덱스 이름 명명
In[6]: ex_df=pd.DataFrame([[0,1,2], [3,4,5], [8,7,9]], columns=['c0','c1','c2'])
In[7]: ex_df.index.name='c_i'
In[8]: ex_df
Out[8]:
c0 c1 c2
c_i
0 0 1 2
1 3 4 5
2 8 7 9
# index 객체에의 조건식 적용
In[9]: ex_df.query('c_i>=1')
Out[9]:
c0 c1 c2
c_i
1 3 4 5
2 8 7 9
인덱스 이름을 지정하지 않은 경우는 query 표현식에 index라는 이름으로 사용할 수 있다.
index 객체로의 query 메서드 사용 예 2)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
# 예제용 배열 선언 및 인덱스 이름 명명
In[6]: ex_df=pd.DataFrame([[0,1,2], [3,4,5], [8,7,9]], columns=['c0','c1','c2'])
In[7]: ex_df.index.name='c_i'
In[8]: ex_df
Out[8]:
c0 c1 c2
c_i
0 0 1 2
1 3 4 5
2 8 7 9
# index 객체에의 조건식 적용
In[10]: ex_df.query('index>=1')
Out[10]:
c0 c1 c2
c_i
1 3 4 5
2 8 7 9
만약 인덱스의 이름과 열의 이름이 겹치는 경우에는 열의 이름이 우선순위가 높다.
이 경우 사용자가 인덱스를 query 표현식에서 사용하길 원하다면, 'index'를 인식자로서 사용하면 된다.
열의 레이블명과 인덱스 객체명이 동일할 시 우선순위를 보여주는 예)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
# 예제용 배열 선언 및 인덱스 이름 명명
In[11]: ex_df=pd.DataFrame([[0,1,2], [3,4,5], [8,7,9]], columns=['c0','c1','c2'])
In[12]: ex_df.index.name='c0'
In[13]: ex_df
Out[13]:
c0 c1 c2
c0
0 0 1 2
1 3 4 5
2 8 7 9
# 인덱스 객체의 이름과 열의 이름이 같을 시 우선순위를 보여주는 예
In[14]: ex_df.query('c0<2')
Out[14]:
c0 c1 c2
c0
0 0 1 2
In[15]: ex_df.query('index<2')
Out[15]:
c0 c1 c2
c0
0 0 1 2
1 3 4 5
참고사항
만약 사용자가 열의 이름을 index로 설정하였다면, 인덱스 객체를 ilevel_0로 참조할 수 있다.
그러나 이런 상황에서는 열의 이름을 다시 설정하는 것을 고려하는 편이 더 낫다.
멀티인덱스에서의 사용 예제 |
멀티인덱스를 사용 했을 경우에도 query 메서드가 적용이 가능하다.
아래 예제는 멀티인덱스에서의 이름 명을 지정했을 경우와 지정하지 않았을 경우에 query메서드를 적용한 예제를 보여준다.
멀티인덱스에서의 query 메서드 적용 예)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
# 예제용 배열 선언 및 인덱스 이름 명명
In[16]: index_mul=pd.MultiIndex.from_tuples([('a1','b1'),('a1','b2'),('a2','b1'),('a2','b2')])
In[17]: ex_df_mul=pd.DataFrame([[0,1,2],[3,4,5],[6,7,8],[9,10,11]],index=index_mul)
In[18]: ex_df_mul.index.names=['L1','L2'] # 인덱스 이름 명명
In[19]: ex_df_mul
Out[19]:
0 1 2
L1 L2
a1 b1 0 1 2
b2 3 4 5
a2 b1 6 7 8
b2 9 10 11
# 멀티인덱스에서의 query 사용
In[20]: ex_df_mul.query(' L1=="a1" ')
Out[20]:
0 1 2
L1 L2
a1 b1 0 1 2
b2 3 4 5
# 멀티인덱스 이름 초기화시 query 사용
n[21]: ex_df_mul.index.names=[None, None] # 멀티인덱스 이름 초기화
n[22]: ex_df_mul.query('ilevel_0=="a1"')
Out[22]:
0 1 2
a1 b1 0 1 2
b2 3 4 5
※ ilevel_0은 0번째 index 단계를 의미한다.
in 및 not in 연산자의 사용 예제 |
in과 not in 연산자
query()는 또한 파이썬에서 제공하는 in과 not in 비교연산자를 지원한다.
isin 메서드를 사용하는 것과 거의 동등한 결과를 도출한다.
query 메서드에서의 in 및 not in 연산자 적용 예)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
# 예제용 배열 선언
In[23]: ex_df=pd.DataFrame([[0,1,3], [1,2,4], [2,3,6]], index=['r0','r1','r2'], columns=['c0','c1','c2'])
In[24]: ex_df
Out[24]:
c0 c1 c2
r0 0 1 3
r1 1 2 4
r2 2 3 6
# query에서의 in과 not in 사용 예제
In[25]: ex_df.query('c0 in c1')
Out[25]:
c0 c1 c2
r1 1 2 4
r2 2 3 6
In[26]: ex_df.query('c0 not in c1')
Out[26]:
c0 c1 c2
r0 0 1 3
참고사항
아래 내용들은 TMI 이므로 굳이 몰라도 될 듯 하다.
query() 메서드에서 문자열 표현식을 입력받는 것은 기본적으로 numexpr을 사용한다.
그러나 numexpr는 in과 not in 연산자를 제공하지 않는다.
즉, 표현식에서 in/not in 평범한 파이썬 문법이다.
예를들어 아래 표현식에서
ex_df.query('c0 in c1 + c2 + c3')
in 연산은 평범한 파이썬 문법으로 처리되고 c1 + c2 + c3는 numexpr으로 처리된다.
즉, 기본적으로 어느 연산이건 numexpr으로 처리가 된다고 생각하면 된다.
list 객체와 == / != 연산자의 사용
==/!=연산자를 사용하여 값들의 리스트(list)를 비교하는 것은 in과 not in 과 유사하게 작동한다.
○ 아래 예제를 살펴보면 두 연산 결과가 위의 예제와 동일한 것을 확인할 수 있다.
query 메서드에서의 리스트에 == 및 != 연산자 적용 예)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
# 예제용 배열 선언
In[27]: ex_df=pd.DataFrame([[0,1,3], [1,2,4], [2,3,6]], index=['r0','r1','r2'], columns=['c0','c1','c2'])
In[28]: ex_df
Out[28]:
c0 c1 c2
r0 0 1 3
r1 1 2 4
r2 2 3 6
# query에서의 in과 not in 사용 예제
In[29]: ex_df.query('c0 == [1, 2, 3]')
Out[29]:
c0 c1 c2
r1 1 2 4
r2 2 3 6
In[30]: ex_df.query('c0 != [1, 2, 3]')
Out[30]:
c0 c1 c2
r0 0 1 3
~/not 연산자
사용자는 not 혹은 ~연산자를 사용한 불린 표현식을 사용할 수 있다.
○ 아래 예제는 not/~ 연산자를 사용한 예제이다.
query 메서드에서의 ~/not 연산자 적용 예)
# pandas와 numpy의 import
In[2]: import pandas as pd
In[3]: import numpy as np
# 예제용 배열 선언
In[31]: ex_df=pd.DataFrame([[0,1,3, True], [1,2,4, False], [2,3,6, True]], index=['r0','r1','r2'], columns=['c0','c1','c2','c_bool'])
In[32]: ex_df
Out[32]:
c0 c1 c2 c_bool
r0 0 1 3 True
r1 1 2 4 False
r2 2 3 6 True
# ~/not 연산 사용 예제
In[33]: ex_df.query('c_bool')
Out[33]:
c0 c1 c2 c_bool
r0 0 1 3 True
r2 2 3 6 True
# 예제용 배열 선언
In[34]: ex_df.query('~c_bool')
Out[34]:
c0 c1 c2 c_bool
r1 1 2 4 False
In[35]: ex_df.query('not c_bool')
Out[35]:
c0 c1 c2 c_bool
r1 1 2 4 False
위의 예제들을 적절히 조합하면 복잡한 조건식도 사용하는 것이 가능하다.
query 메서드 세부 옵션 |
DataFrame.query(self, expr, inplace=False, **kwargs) |
문자열로 구성된 불린 표현식을 사용하여 DataFrame의 열을 선택한다.
expr: str
연산을 수행하기 위한 query 문자열을 입력받는다.
사용자는 @ 문자를 앞에 붙임으로써 환경변수를 참조할 수 있다.
-@a+b
공백을 포함하는 열 이름은 백틱(`)으로 묶어서 참조 할 수 있다.
예를들어 만약 열중 하나가 a a와 b를 사용하여 더하기를 원한다면 사용자는 query표현식에 `a a` + b라 입력하면된다.
※ 백틱은 따옴표(')와 다르므로 주의하자.
inplace: bool
query가 데이터를 수정하거나 혹은 수정된 카피를 반환할지 여부를 결정한다.
**kwarys
eval() 메서드에 대한 자료를 참고하자.
참고사항
표현식에 의한 평가결과 결과는 처음에는 DataFrame.loc에 전달된다.
만약 다차원 키(key)때문에 실패한다면, 결과는 DataFrame.__getitem__()에 전달된다.
이 메서드는 전달된 query를 평가하기 위해 최상위 단계인 eval() 함수를 사용한다.
query() 메서드는 기본적으로 약간 수정된 파이썬 문법을 사용한다.
예를들어 &와 |는 불린 연산자의 사촌격인 and와 or의 우선순위를 가진다.
이것은 문법적으로 유효하나 의미론적으로는 다르다.
사용자는 키워드 인자인 parser='python' 입력함으로써 표현식의 의미를 바꿀 수 있다.
이것은 같은 표현식이 순수 python과 동일하게 만든다.
마찬가지로 사용자는 engine='python'을 입력하여 백앤드처럼 파이썬 고유기능을 이용한 표현식을 사용할 수 있다.
이것은 권장되지 않는데, numexpr 엔진을 사용하는 것에 비해 비효율적이다.
DataFrame 인스턴스(instance)안에 내장되어 있는 DataFrame.index와 DataFrame.columns 어트리뷰트(attribute)는 query 네임스페이스에 기본적으로 내장되어있다.
그리고 이는 사용자에게 프레임에서의 열처럼 인덱스와 열을 처리할 수 있도록 도와준다.
식별자(identifier) index는 프레임의 인덱스에대해 사용되어지고, 사용자는 또한 인덱스의 이름을 query에서 식별할 수 있게 사용할 수 있다.
파이썬의 키워드들은 식별자로써 사용될 수 없다는 사실을 알고있도록 하자.
|
|
|
| 참고자료 https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.query.html |
|
|
|
|
'Python > Pandas' 카테고리의 다른 글
index(인덱스)객체의 생성, 개요, 처리방법-pandas(20) (0) | 2019.11.03 |
---|---|
get 및 lookup 메서드 설명, 옵션, 사용 예제 -pandas(19) (0) | 2019.11.01 |
where 및 mask 메서드 옵션, 설명, 사용 예-pandas(17) (0) | 2019.10.28 |
isin 메서드 옵션 및 설명과 인덱싱-pandas(16) (0) | 2019.10.26 |
패스트 인덱싱(.at, .iat)-pandas(15) (0) | 2019.10.24 |
댓글