панды: несколько условий при индексировании фрейма данных-неожиданное поведение


я фильтрую строки в фрейме данных по значениям в двух столбцах.

по какой-то причине оператор OR ведет себя так, как я ожидал бы, и оператор будет вести себя и наоборот.

мой тестовый код:

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 отказаться от них. Я бы ожидайте прямо противоположного результата. Кто-нибудь может объяснить это поведение, пожалуйста?

Я использую панды 0.13.1.

2 52

2 ответа:

как вы можете видеть, оператор AND отбрасывает каждую строку, в которой хотя бы один значение равно -1. С другой стороны, оператор OR требует и того, и другого значений должна быть равна 1, чтобы отбросить их.

это верно. Помните, что вы пишете условие в терминах того, что вы хотите сохранить, не с точки зрения того, что вы хотите бросить. Ибо df1:

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

вы говорите: "держите строки, в которых df.a не -1, а df.b это не -1", что то же самое, что отбрасывать каждую строку, в которой хотя бы одно значение равно -1.

на df2:

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

вы говорите: "держите строки, в которых либо df.a или df.b не является -1", что совпадает с удалением строк, где оба значения равны -1.

PS: цепной доступ, как df['a'][1] = -1 может доставить вам неприятности. Это лучше, чтобы войти в привычку использовать .loc и .iloc.

можно использовать query (), например:

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