Подтвердить что ты не робот

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

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

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

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

import pandas as pd

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

# let 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.

4b9b3361

Ответ 1

Как вы можете видеть, оператор И оставляет каждую строку, в которой, по крайней мере, один значение равно -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.

Ответ 2

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

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

Ответ 3

Немного математической теории логики здесь:

"НЕ А И НЕ Б" - это то же самое, что "НЕ (ИЛИ Б)", поэтому:

"a NOT -1 И b NOT -1" эквивалентно "NOT (a - -1 ИЛИ b - -1)", что противоположно (дополнение) к "(a - -1 ИЛИ b -" -1)".

Поэтому, если вы хотите получить противоположный результат, df1 и df2 должны быть такими, как показано ниже:

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