Filtruję wiersze w ramce danych według wartości w dwóch kolumnach.
Z jakiegoś powodu operator OR zachowuje się tak, jak powinienem oczekiwać operatora AND i odwrotnie.
Mój kod testowy:
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 (|)',])
A wynik:
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]
Jak widać, AND
operator porzuca każdy wiersz, w którym przynajmniej jedna wartość jest równa -1
. Z drugiej strony OR
operator wymaga, aby obie wartości były równe, aby -1
je usunąć. Spodziewałbym się dokładnie odwrotnego wyniku. Czy ktoś mógłby wyjaśnić to zachowanie?
Używam pand 0.13.1.
python
pandas
boolean-logic
Wojciech Walczak
źródło
źródło
df.query
ipd.eval
wydaje się, że dobrze pasuje do tego przypadku użycia. Aby uzyskać informacje na tematpd.eval()
rodziny funkcji, ich funkcji i przypadków użycia, odwiedź stronę Dynamic Expression Evaluation w pandach przy użyciu pd.eval () .Odpowiedzi:
Zgadza się. Pamiętaj, że piszesz warunek w kategoriach tego, co chcesz zachować , a nie tego, co chcesz upuścić. Dla
df1
:Mówisz „zachowaj wiersze, w których
df.a
nie jest -1 idf.b
nie jest -1”, co jest tym samym, co usuwanie każdego wiersza, w którym co najmniej jedna wartość to -1.Dla
df2
:Mówisz „keep wiersze, w których albo
df.a
czydf.b
nie jest -1”, która jest taka sama jak upuszczenie wiersze gdzie obie wartości -1.PS: dostęp łańcuchowy
df['a'][1] = -1
może wpędzić cię w kłopoty. Lepiej nabrać nawyku używania.loc
i.iloc
.źródło
DataFrame.query()
tu też dobrze działa.df.query('a != -1 or b != -1')
.&
i|
nadand
ior
?and
ior
ma podstawową semantykę Pythona, której nie można modyfikować.&
i|
, z drugiej strony, mają odpowiadające specjalnych metod, które kontrolują swoje zachowania. (Oczywiście w ciągach zapytań możemy zastosować dowolne analizowanie, które nam się podoba.)df[True & False]
niedf[(True) & (False)]
udaje (nie testowano na tym przykładzie)Możesz użyć query () , czyli:
źródło
Tutaj trochę teorii logiki matematycznej :
„NOT a AND NOT b” to to samo, co „NOT (a OR b)” , więc:
„a NOT -1 AND b NOT -1” jest odpowiednikiem „NOT (a is -1 OR b is -1)” , które jest przeciwieństwem (Complement) z „(a jest -1 LUB b jest -1)” .
Więc jeśli chcesz uzyskać dokładnie odwrotny wynik, df1 i df2 powinny wyglądać jak poniżej:
źródło