Логический оператор для булевой индексации в панд


Я работаю с булевым индексом в панд. Вопрос в том, почему утверждение:

a[(a['some_column']==some_number) & (a['some_other_column']==some_other_number)]

работает, а

a[(a['some_column']==some_number) and (a['some_other_column']==some_other_number)]
ошибки?

пример:

a=pd.DataFrame({'x':[1,1],'y':[10,20]})

In: a[(a['x']==1)&(a['y']==10)]
Out:    x   y
     0  1  10

In: a[(a['x']==1) and (a['y']==10)]
Out: ValueError: The truth value of an array with more than one element is ambiguous.     Use a.any() or a.all()
1 59

1 ответ:

когда вы говорите

(a['x']==1) and (a['y']==10)

вы неявно просите Python конвертировать (a['x']==1) и (a['y']==10) к логическим значениям.

массивы NumPy (длиной больше 1) и объекты Pandas, такие как Series, не имеют логического значения-другими словами, они поднимают

ValueError: The truth value of an array is ambiguous. Use a.empty, a.any() or a.all().

при использовании в качестве логического значения. Это потому, что его непонятно, когда это должно быть правдой или ложью. Некоторые пользователи могут предположить, что они истинны, если они имеют ненулевую длину, как список Python. Другие могут желать, чтобы это было правдой, только если все ее элементы истинны. Другие могут захотеть, чтобы это было правдой, если любой из его элементов верны.

потому что есть так много противоречивых ожиданий, дизайнеры NumPy и панды отказываются угадывать, а вместо этого поднимают ValueError.

вместо этого вы должны быть явными, вызвав empty(),all() или any() метод, чтобы указать, какое поведение жаждать.

в этом случае, однако, похоже, что вы не хотите логической оценки, вы хотите элемент-мудрый логично-а. Вот что такое & бинарный оператор выполняет:

(a['x']==1) & (a['y']==10)

возвращает булевский массив.


кстати, как alexpmil notes, скобки обязательны, так как & выше приоритет операторов чем ==. Без скобок, a['x']==1 & a['y']==10 будет оценивается как a['x'] == (1 & a['y']) == 10 что в свою очередь было бы эквивалентно цепному сравнению (a['x'] == (1 & a['y'])) and ((1 & a['y']) == 10). Это выражение формы Series and Series. Использование and С двумя сериями снова вызовет то же самое ValueError как выше. Вот почему скобки являются обязательными.