Usando operadores lógicos en la construcción de un DataFrame Pandas

Tengo dos fragmentos de código de pandas que creo que deberían ser equivalentes, pero el segundo no hace lo que espero.

# snippet 1 data = all_data[[((np.isfinite(all_data[self.design_metric][i]) and all_data['Source'][i] == 2)) or ((np.isfinite(all_data[self.actual_metric][i]) and all_data['Source'][i] != 2)) for i in range(len(all_data))]] # snippet 2 data = all_data[(all_data['Source'] == 2 & np.isfinite(all_data[self.design_metric])) | (all_data['Source'] != 2 & np.isfinite(all_data[self.actual_metric]))] 

Cada sección (por ejemplo, all_data['Source'] == 2 ) hace lo que espero por sí misma, pero parece que estoy haciendo algo mal con los operadores lógicos, ya que el resultado final sale con un resultado diferente a la lista de comprensión. versión.

El operador & enlaza más fuertemente que == (o cualquier operador de comparación). Consulte la documentación . Un ejemplo más simple es:

 >>> 2 == 2 & 3 == 3 False 

Esto se debe a que se agrupa como 2 == (2 & 3) == 3 , y luego se invoca el encadenamiento de comparación. Esto es lo que está pasando en tu caso. Necesitas poner paréntesis alrededor de cada comparación.

  data = all_data[((all_data['Source'] == 2) & np.isfinite(all_data[self.design_metric])) | ((all_data['Source'] != 2) & np.isfinite(all_data[self.actual_metric]))] 

Note los paréntesis adicionales alrededor de las comparaciones == y != .

Junto con la prioridad, hay una diferencia entre los operadores AND y, el primero es booleano y el último binario a nivel binario. Además, debe tener en cuenta las expresiones boolead.

Ver ejemplos en el siguiente fragmento de código:

expresiones lógicas

 >>> 1 and 2 1 >>> '1' and '2' '1' >>> 0 == 1 and 2 == 0 or 0 0 

operadores bitwise

 >>> 1 & 2 0 >>> '1' & '2' Traceback (most recent call last): ... TypeError: unsupported operand type(s) for &: 'str' and 'str' >>> 0 == 1 & 2 == 0 | 0 True