¿Cómo seleccionar filas en un DataFrame entre dos valores, en Python Pandas?

99

Estoy tratando de modificar un DataFrame dfpara que solo contenga filas para las cuales los valores en la columna closing_priceestán entre 99 y 101 e intento hacer esto con el código a continuación.

Sin embargo, me sale el error

ValueError: el valor de verdad de una serie es ambiguo. Utilice a.empty, a.bool (), a.item (), a.any () o a.all ()

y me pregunto si hay una manera de hacer esto sin usar bucles.

df = df[(99 <= df['closing_price'] <= 101)]
usuario131983
fuente
El problema aquí es que no puede comparar un escalar con una matriz, de ahí el error, para las comparaciones debe usar los operadores bit a bit y encerrarlos entre paréntesis debido a la precedencia del operador
EdChum
df.queryy pd.evalparecen buenos ajustes para este caso de uso. Para obtener información sobre la pd.eval()familia de funciones, sus características y casos de uso, visite Evaluación de expresión dinámica en pandas usando pd.eval () .
cs95

Respuestas:

103

Debe usar ()para agrupar su vector booleano para eliminar la ambigüedad.

df = df[(df['closing_price'] >= 99) & (df['closing_price'] <= 101)]
Jianxun Li
fuente
164

Considere también series entre :

df = df[df['closing_price'].between(99, 101)]
Parfait
fuente
5
La opción inclusive=Truese usa de forma predeterminada en between, por lo que puede consultar de esta maneradf = df[df['closing_price'].between(99, 101)]
Anton Ermakov
3
¡Esta es la mejor respuesta! ¡gran trabajo!
PEBKAC
¿Existe la funcionalidad "no entre" en los pandas? No lo encuentro.
dsugasa
3
@dsugasa, usa el operador de tilde con between.
Parfait
1
@dsugasa egdf = df[~df['closing_price'].between(99, 101)]
Ene33
22

hay una alternativa mejor: use el método query () :

In [58]: df = pd.DataFrame({'closing_price': np.random.randint(95, 105, 10)})

In [59]: df
Out[59]:
   closing_price
0            104
1             99
2             98
3             95
4            103
5            101
6            101
7             99
8             95
9             96

In [60]: df.query('99 <= closing_price <= 101')
Out[60]:
   closing_price
1             99
5            101
6            101
7             99

ACTUALIZACIÓN: respondiendo al comentario:

Me gusta la sintaxis aquí, pero fracasé al intentar combinarla con la expresión; df.query('(mean + 2 *sd) <= closing_price <=(mean + 2 *sd)')

In [161]: qry = "(closing_price.mean() - 2*closing_price.std())" +\
     ...:       " <= closing_price <= " + \
     ...:       "(closing_price.mean() + 2*closing_price.std())"
     ...:

In [162]: df.query(qry)
Out[162]:
   closing_price
0             97
1            101
2             97
3             95
4            100
5             99
6            100
7            101
8             99
9             95
MaxU
fuente
Me gusta la sintaxis aquí, pero fracasé al intentar combinarla con la expresión; df.query ('(mean + 2 * sd) <= closed_price <= (mean + 2 * sd)')
mapeo dom
1
@mappingdom, ¿qué es meany sd? ¿Son esos nombres de columna?
MaxU
no, son la media calculada y la desviación estándar almacenada como flotante
mapeo dom
@mappingdom, ¿a qué te refieres con "almacenado"?
MaxU
@mappingdom, he actualizado mi publicación, ¿es eso lo que estabas pidiendo?
MaxU
9

también puedes usar el .between()método

emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv")

emp[emp["Salary"].between(60000, 61000)]

Salida

ingrese la descripción de la imagen aquí

Riz.Khan
fuente
6
newdf = df.query('closing_price.mean() <= closing_price <= closing_price.std()')

o

mean = closing_price.mean()
std = closing_price.std()

newdf = df.query('@mean <= closing_price <= @std')
crashMOGWAI
fuente
3

Si está tratando con múltiples valores y múltiples entradas, también puede configurar una función de aplicación como esta. En este caso, filtrar un marco de datos para ubicaciones de GPS que se encuentran dentro de ciertos rangos.

def filter_values(lat,lon):
    if abs(lat - 33.77) < .01 and abs(lon - -118.16) < .01:
        return True
    elif abs(lat - 37.79) < .01 and abs(lon - -122.39) < .01:
        return True
    else:
        return False


df = df[df.apply(lambda x: filter_values(x['lat'],x['lon']),axis=1)]
gorrión
fuente
1

En lugar de esto

df = df[(99 <= df['closing_price'] <= 101)]

Deberías usar esto

df = df[(df['closing_price']>=99 ) & (df['closing_price']<=101)]

Tenemos que usar los operadores lógicos bit a bit de NumPy |, &, ~, ^ para las consultas compuestas. Además, los paréntesis son importantes para la precedencia de los operadores.

Para obtener más información, puede visitar el enlace: Comparaciones, máscaras y lógica booleana

Rushabh Agarwal
fuente