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

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

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

Я использую pandas 0.13.1.

2 ответов


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

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

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

вы говорите: "держите строки, в которых df.a не -1, а df.b isn'T -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')