TLDR; 팬더의 논리 연산자는 &
, |
및 ~
, 괄호는 (...)
중요하다!
파이썬이다 and
, or
및 not
논리 연산자는 스칼라와 함께 작동하도록 설계되었습니다. 따라서 Pandas는 이 기능의 벡터화 된 (요소 별) 버전 을 달성하기 위해 더 나은 작업을 수행하고 비트 연산자를 재정의해야했습니다 .
파이썬에서 다음 그래서 ( exp1
및 exp2
부울 결과로 평가 표현입니다) ...
exp1 and exp2 # Logical AND
exp1 or exp2 # Logical OR
not exp1 # Logical NOT
...로 번역됩니다 ...
exp1 & exp2 # Element-wise logical AND
exp1 | exp2 # Element-wise logical OR
~exp1 # Element-wise logical NOT
팬더를 위해.
논리 연산을 수행하는 과정에서을 얻는 ValueError
다면 그룹화를 위해 괄호를 사용해야합니다.
(exp1) op (exp2)
예를 들어
(df['col1'] == x) & (df['col2'] == y)
등등.
부울 인덱싱 : 일반적인 작업은 논리 조건을 통해 부울 마스크를 계산하여 데이터를 필터링하는 것입니다. Pandas는논리 AND,논리 OR 및논리 NOT에대해 세 가지 연산자를제공합니다.&
|
~
다음 설정을 고려하십시오.
np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (5, 3)), columns=list('ABC'))
df
A B C
0 5 0 3
1 3 7 9
2 3 5 2
3 4 7 6
4 8 8 1
논리 AND
를 들어 df
위의, 당신은 <5와 B가> 5.이 개별적으로 각 조건에 대한 마스크를 계산하고이를 AND 연산에 의해 수행되는 모든 행을 반환하고 싶습니다 말한다.
오버로드 된 비트 단위 &
연산자
계속하기 전에이 특정 문서의 발췌 내용을 확인하십시오.
또 다른 일반적인 작업은 데이터를 필터링하기 위해 부울 벡터를 사용하는 것입니다. 연산자는 |
for or
, &
for and
및 ~
for not
입니다. 이 괄호를 사용하여 그룹화해야 같은 식을 평가합니다 기본 파이썬으로 이후 df.A > 2 & df.B < 3
로 df.A > (2 &
df.B) < 3
원하는 평가 순서 인 반면, (df.A > 2) & (df.B <
3)
.
따라서 이것을 염두에두고 요소 별 논리 AND는 비트 연산자로 구현할 수 있습니다 &
.
df['A'] < 5
0 False
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df['B'] > 5
0 False
1 True
2 False
3 True
4 True
Name: B, dtype: bool
(df['A'] < 5) & (df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
그리고 후속 필터링 단계는 간단합니다.
df[(df['A'] < 5) & (df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
괄호는 비트 연산자의 기본 우선 순위를 재정의하는 데 사용되며 조건부 연산자 <
및 보다 우선 순위가 높은 비트 연산자 >
입니다. 파이썬 문서에서 연산자 우선 순위 섹션을 참조하십시오 .
괄호를 사용하지 않으면식이 잘못 평가됩니다. 예를 들어 실수로
df['A'] < 5 & df['B'] > 5
다음과 같이 파싱됩니다.
df['A'] < (5 & df['B']) > 5
어느 것이
df['A'] < something_you_dont_want > 5
( 연쇄 연산자 비교 에 대한 파이썬 문서 참조 )
(df['A'] < something_you_dont_want) and (something_you_dont_want > 5)
어느 것이
# Both operands are Series...
something_else_you_dont_want1 and something_else_you_dont_want2
던지는
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
따라서 실수하지 마십시오! 1
괄호 그룹화 방지
수정은 실제로 매우 간단합니다. 대부분의 연산자에는 DataFrame에 해당하는 바인딩 된 메서드가 있습니다. 개별 마스크가 조건 연산자 대신 함수를 사용하여 구축 된 경우 평가 순서를 지정하기 위해 더 이상 괄호별로 그룹화 할 필요가 없습니다.
df['A'].lt(5)
0 True
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df['B'].gt(5)
0 False
1 True
2 False
3 True
4 True
Name: B, dtype: bool
df['A'].lt(5) & df['B'].gt(5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
유연한 비교 섹션을 참조하십시오 . . 요약하면, 우리는
╒════╤════════════╤════════════╕
│ │ Operator │ Function │
╞════╪════════════╪════════════╡
│ 0 │ > │ gt │
├────┼────────────┼────────────┤
│ 1 │ >= │ ge │
├────┼────────────┼────────────┤
│ 2 │ < │ lt │
├────┼────────────┼────────────┤
│ 3 │ <= │ le │
├────┼────────────┼────────────┤
│ 4 │ == │ eq │
├────┼────────────┼────────────┤
│ 5 │ != │ ne │
╘════╧════════════╧════════════╛
괄호를 피하기위한 또 다른 옵션은 사용하는 것입니다 DataFrame.query
(또는 eval
) :
df.query('A < 5 and B > 5')
A B C
1 3 7 9
3 4 7 6
나는 pd.eval ()을 사용하여 판다 에서 광범위하게 문서화 query
하고 동적 표현 평가를했습니다 .eval
operator.and_
기능적인 방식으로이 작업을 수행 할 수 있습니다. Series.__and__
비트 연산자에 해당하는 내부 호출
import operator
operator.and_(df['A'] < 5, df['B'] > 5)
# Same as,
# (df['A'] < 5).__and__(df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
df[operator.and_(df['A'] < 5, df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
일반적으로 필요하지는 않지만 알고 있으면 유용합니다.
일반화 : np.logical_and
(그리고 logical_and.reduce
)
또 다른 대안은을 사용 np.logical_and
하는 것으로 괄호 그룹화가 필요하지 않습니다.
np.logical_and(df['A'] < 5, df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
Name: A, dtype: bool
df[np.logical_and(df['A'] < 5, df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
np.logical_and
는 ufunc (범용 함수) 이며 대부분의 ufunc에는 reduce
메소드가 있습니다. 이는 logical_and
AND에 여러 마스크가 있는 경우 일반화하기가 더 쉽다는 것을 의미합니다 . 예를 들어, 및 마스크 m1
와 m2
와 m3
함께 &
, 당신은해야 할 것
m1 & m2 & m3
그러나 더 쉬운 옵션은
np.logical_and.reduce([m1, m2, m3])
보다 복잡한 논리 (예 : 목록 이해에서 마스크를 동적으로 생성하고 모든 마스크를 추가)를 사용하여이를 기반으로 구축 할 수 있으므로 강력합니다.
import operator
cols = ['A', 'B']
ops = [np.less, np.greater]
values = [5, 5]
m = np.logical_and.reduce([op(df[c], v) for op, c, v in zip(ops, cols, values)])
m
# array([False, True, False, True, False])
df[m]
A B C
1 3 7 9
3 4 7 6
1-이 시점에서 내가 쇠퇴하고 있다는 것을 안다. 이것은이다 매우 , 매우 일반적인 초보자의 실수를 아주 철저하게 설명해야합니다.
논리 OR
를 들어 df
위의 모든 A 열과 == 3 또는 B == 7을 반환하고 싶습니다 말한다.
비트 단위로 과부하 |
df['A'] == 3
0 False
1 True
2 True
3 False
4 False
Name: A, dtype: bool
df['B'] == 7
0 False
1 True
2 False
3 True
4 False
Name: B, dtype: bool
(df['A'] == 3) | (df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
dtype: bool
df[(df['A'] == 3) | (df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
아직 논리 및 위 섹션을 읽으 십시오. 여기에 모든 경고 사항이 적용됩니다.
또는이 작업을 사용하여 지정할 수 있습니다
df[df['A'].eq(3) | df['B'].eq(7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
operator.or_
Series.__or__
후드 아래에서
호출 합니다.
operator.or_(df['A'] == 3, df['B'] == 7)
# Same as,
# (df['A'] == 3).__or__(df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
dtype: bool
df[operator.or_(df['A'] == 3, df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
np.logical_or
두 가지 조건의 경우 다음을 사용하십시오 logical_or
.
np.logical_or(df['A'] == 3, df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df[np.logical_or(df['A'] == 3, df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
여러 마스크의 경우 다음을 사용하십시오 logical_or.reduce
.
np.logical_or.reduce([df['A'] == 3, df['B'] == 7])
# array([False, True, True, True, False])
df[np.logical_or.reduce([df['A'] == 3, df['B'] == 7])]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
논리 NOT
다음과 같은 마스크가 주어집니다.
mask = pd.Series([True, True, False])
모든 부울 값을 반전시켜야하는 경우 (최종 결과는 [False, False, True]
) 아래의 방법 중 하나를 사용할 수 있습니다.
비트 단위 ~
~mask
0 False
1 False
2 True
dtype: bool
다시 말하지만, 표현식은 괄호로 묶어야합니다.
~(df['A'] == 3)
0 True
1 False
2 False
3 True
4 True
Name: A, dtype: bool
이것은 내부적으로 전화
mask.__invert__()
0 False
1 False
2 True
dtype: bool
그러나 직접 사용하지 마십시오.
operator.inv
내부적으로 __invert__
시리즈를 호출 합니다.
operator.inv(mask)
0 False
1 False
2 True
dtype: bool
np.logical_not
이것은 numpy 변형입니다.
np.logical_not(mask)
0 False
1 False
2 True
dtype: bool
참고, np.logical_and
대체 할 수 np.bitwise_and
, logical_or
과 bitwise_or
,과 logical_not
함께 invert
.