pandas : 데이터 프레임을 인덱싱하는 동안 여러 조건-예기치 않은 동작


135

두 열의 값으로 데이터 프레임의 행을 필터링하고 있습니다.

어떤 이유로 OR 연산자는 AND 연산자가 예상하는 것처럼 작동하며 그 반대의 경우도 마찬가지입니다.

내 테스트 코드 :

import pandas as pd

df = pd.DataFrame({'a': range(5), 'b': range(5) })

# let's insert some -1 values
df['a'][1] = -1
df['b'][1] = -1
df['a'][3] = -1
df['b'][4] = -1

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a != -1) | (df.b != -1)]

print pd.concat([df, df1, df2], axis=1,
                keys = [ 'original df', 'using AND (&)', 'using OR (|)',])

그 결과 :

      original df      using AND (&)      using OR (|)    
             a  b              a   b             a   b
0            0  0              0   0             0   0
1           -1 -1            NaN NaN           NaN NaN
2            2  2              2   2             2   2
3           -1  3            NaN NaN            -1   3
4            4 -1            NaN NaN             4  -1

[5 rows x 6 columns]

보시다시피 AND연산자는 적어도 하나의 값이 인 모든 행을 삭제합니다 -1. 반면에 OR연산자는 두 값을 모두 삭제하려면 두 값이 같아야 -1합니다. 나는 정확히 반대의 결과를 기대할 것입니다. 누구든지이 행동을 설명해 주시겠습니까?

pandas 0.13.1을 사용하고 있습니다.


1
df.query그리고 pd.eval이 사용 사례에 대한 좋은 맞는 것처럼 보인다. pd.eval()함수 제품군, 기능 및 사용 사례 에 대한 정보는 pd.eval ()을 사용하는 pandas의 동적 표현식 평가를 참조하십시오 .
cs95

답변:


211

보시다시피 AND 연산자는 하나 이상의 값이 -1 인 모든 행을 삭제합니다. 반면에 OR 연산자는 두 값을 모두 삭제하려면 -1과 같아야합니다.

맞습니다. 당신은 당신이 떨어 뜨리고 싶은 것이 아니라 당신이 유지 하고 싶은 것에 관한 조건을 작성하고 있다는 것을 기억하세요 . 대상 df1:

df1 = df[(df.a != -1) & (df.b != -1)]

" df.a-1이 아니고 -1이 아닌 행을 유지하십시오"라는 말입니다 df.b. 이는 최소한 하나의 값이 -1 인 모든 행을 삭제하는 것과 같습니다.

대상 df2:

df2 = df[(df.a != -1) | (df.b != -1)]

당신은 "둘 중 하나의 행 계속 말을하는지 df.a또는 df.b하지를 -1"두 값은 -1 행을 삭제와 동일하다.

추신 : 연결 액세스는 df['a'][1] = -1문제를 일으킬 수 있습니다. .loc및 을 사용하는 습관을 갖는 것이 좋습니다 .iloc.


24
DataFrame.query()여기에서도 잘 작동합니다. df.query('a != -1 or b != -1').
Phillip Cloud

5
팬더가 원하는 이유를 알고 일어날 &|이상 andor?
스토브

3
@stoves : 일반 파이썬 코드에서, and그리고 or수정할 수 없습니다 기본 파이썬 의미를 가지고있다. &그리고 |, 다른 한편으로는, 자신의 동작을 제어하는 특별한 방법을 해당합니다. (물론 쿼리 문자열에서 원하는 구문 분석을 자유롭게 적용 할 수 있습니다.)
DSM

흥미롭게도 df[True & False]실패한 것처럼 보이지만 df[(True) & (False)]성공합니다 (이 예제에서 테스트되지 않음)
3pitt

이런 종류의 구문을 여러 줄로 나눌 수 있습니까? 대부분의 PEP8은 무엇입니까?
tommy.carstensen

41

query () 사용할 수 있습니다 .

df_filtered = df.query('a == 4 & b != 2')

이 구문이 더 의미가 있다고 생각하는 상황이 있습니다. 예 : df.query ( ''(a == 4 & b! = 2) | c == 3 ")
Aus_10

9

여기에 약간의 수학적 논리 이론이 있습니다.

"NOT a AND NOT b""NOT (a OR b)" 와 동일하므로 :

"a NOT -1 AND b NOT -1""(a is -1 OR b is -1)"의 반대 (보완) 인 "NOT (a is -1 OR b is -1)"과 동일 합니다.

따라서 정반대의 결과를 원한다면 df1 및 df2는 다음과 같아야합니다.

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a == -1) | (df.b == -1)]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.