2017-02-20 14 views
5

Właśnie zauważyłem to:pandy i operator logiczny i bez wsporników daje różne wyniki

df[df.condition1 & df.condition2] 
df[(df.condition1) & (df.condition2)] 

Dlaczego wyjście z tych dwóch linii różnią?


Nie mogę udostępnić dokładne dane, ale mam zamiar starać się zapewnić jak najwięcej szczegółów, jak tylko mogę:

df[df.col1 == False & df.col2.isnull()] # returns 33 rows and the rule `df.col2.isnull()` is not in effect 
df[(df.col1 == False) & (df.col2.isnull())] # returns 29 rows and both conditions are applied correctly 

Dzięki @jezrael i @ayhan, tutaj jest to, co się stało, i pozwól mi posłużyć się przykładem dostarczone przez @jezael:

df = pd.DataFrame({'col1':[True, False, False, False], 
        'col2':[4, np.nan, np.nan, 1]}) 

print (df) 
    col1 col2 
0 True 4.0 
1 False NaN 
2 False NaN 
3 False 1.0 

Jeśli spojrzeć na wiersz 3:

col1 col2 
3 False 1.0 

i sposób pisałem warunek:

df.col1 == False & df.col2.isnull() # is equivalent to False == False & False 

Ponieważ znak & ma wyższy priorytet niż ==, bez nawiasów False == False & False jest równoznaczne z:

False == (False & False) 
print(False == (False & False)) # prints True 

ze wspornikami:

print((False == False) & False) # prints False 

myślę, że jest trochę łatwiej zilustrować ten problem z numerami:

print(5 == 5 & 1) # prints False, because 5 & 1 returns 1 and 5==1 returns False 
print(5 == (5 & 1)) # prints False, same reason as above 
print((5 == 5) & 1) # prints 1, because 5 == 5 returns True, and True & 1 returns 1 

Więc wnioski: zawsze dodać nawiasy !!!

Życzę mogę podzielić punkty odpowiedź na oba @jezrael i @ayhan :(

Odpowiedz

9

nie ma różnicy między df[condition1 & condition2] i df[(condition1) & (condition2)] Różnica pojawia się, gdy piszesz ekspresję i operatora & ma pierwszeństwo.

df = pd.DataFrame(np.random.randint(0, 10, size=(5, 3)), columns=list('abc'))  
df 
Out: 
    a b c 
0 5 0 3 
1 3 7 9 
2 3 5 2 
3 4 7 6 
4 8 8 1 

condition1 = df['a'] > 3 
condition2 = df['b'] < 5 

df[condition1 & condition2] 
Out: 
    a b c 
0 5 0 3 

df[(condition1) & (condition2)] 
Out: 
    a b c 
0 5 0 3 

jednak po wpisaniu go w ten sposób zobaczysz błąd:

df[df['a'] > 3 & df['b'] < 5] 
Traceback (most recent call last): 

    File "<ipython-input-7-9d4fd21246ca>", line 1, in <module> 
    df[df['a'] > 3 & df['b'] < 5] 

    File "/home/ayhan/anaconda3/lib/python3.5/site-packages/pandas/core/generic.py", line 892, in __nonzero__ 
    .format(self.__class__.__name__)) 

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). 

Wynika to z faktu, że najpierw jest oceniany 3 & df['b'] (w twoim przykładzie odpowiada to False & df.col2.isnull()). Więc trzeba grupie warunki w nawiasach:

df[(df['a'] > 3) & (df['b'] < 5)] 
Out[8]: 
    a b c 
0 5 0 3 
1

Masz rację, to jest różnica i myślę, że nie ma problemu z pierwszeństwem operatorów - sprawdź docs:

df = pd.DataFrame({'col1':[True, False, False, False], 
        'col2':[4, np.nan, np.nan, 1]}) 

print (df) 
    col1 col2 
0 True 4.0 
1 False NaN 
2 False NaN 
3 False 1.0 

# operator & precedence 
print (df[df.col1 == False & df.col2.isnull()]) 
    col1 col2 
1 False NaN 
2 False NaN 
3 False 1.0 

# operator == precedence bacause in brackets 
print (df[(df.col1 == False) & (df.col2.isnull())]) 
    col1 col2 
1 False NaN 
2 False NaN 

Wydaje znalazłem w docs - 6.16. Pierwszeństwo operatora gdzie zobaczyć & mają wyższy priorytet jako ==:

Operator        Description 

lambda         Lambda expression 
if – else        Conditional expression 
or          Boolean OR 
and          Boolean AND 
not x         Boolean NOT 
in, not in, is, is not,     Comparisons, including membership tests  
<, <=, >, >=, !=, ==     and identity tests 
|          Bitwise OR 
^          Bitwise XOR 
&          Bitwise AND 

(expressions...), [expressions...],  Binding or tuple display, list display,  
{key: value...}, {expressions...}  dictionary display, set display 
+0

Więc który operator wziął priorytet, nadal jestem zdezorientowany. – Cheng

+0

'Poniższa tabela podsumowuje pierwszeństwo operatora w języku Python, od najniższego pierwszeństwa (najmniejszego wiązania) do najwyższego priorytetu (najbardziej wiążącego). "więc myślę, że' & 'ma wyższy priorytet niż' == '. Zobacz zaktualizowany OP – Cheng

Powiązane problemy