¿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)]

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)]

164

Considere también series entre :

df = df[df['closing_price'].between(99, 101)]

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

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í


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')

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)]

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.