¿Cómo seleccionar filas de un DataFrame basado en valores en alguna columna en Python Pandas?

En SQL, usaría:

SELECT *
FROM table
WHERE colume_name = some_value

Traté de mirar la documentación de los pandas pero no encontré la respuesta de inmediato.

1791
szli 12 jun. 2013 a las 21:42

9 respuestas

La mejor respuesta

Para seleccionar filas cuyo valor de columna sea igual a un escalar, some_value, use ==:

df.loc[df['column_name'] == some_value]

Para seleccionar filas cuyo valor de columna esté en un iterable, some_values, use isin:

df.loc[df['column_name'].isin(some_values)]

Combina múltiples condiciones con &:

df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]

Tenga en cuenta los paréntesis. Debido a las reglas de precedencia del operador de Python, & se une más estrictamente que <= y >=. Por lo tanto, los paréntesis en el último ejemplo son necesarios. Sin los paréntesis

df['column_name'] >= A & df['column_name'] <= B

Se analiza como

df['column_name'] >= (A & df['column_name']) <= B

Lo que resulta en un El valor de verdad de una serie es un error ambiguo.


Para seleccionar filas cuyo valor de columna no sea igual some_value, use !=:

df.loc[df['column_name'] != some_value]

isin devuelve una Serie booleana, por lo que para seleccionar filas cuyo valor sea no en some_values, niegue la Serie booleana usando ~:

df.loc[~df['column_name'].isin(some_values)]

Por ejemplo,

import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})
print(df)
#      A      B  C   D
# 0  foo    one  0   0
# 1  bar    one  1   2
# 2  foo    two  2   4
# 3  bar  three  3   6
# 4  foo    two  4   8
# 5  bar    two  5  10
# 6  foo    one  6  12
# 7  foo  three  7  14

print(df.loc[df['A'] == 'foo'])

Rendimientos

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Si tiene varios valores que desea incluir, colóquelos en un list (o más generalmente, cualquier iterable) y use isin:

print(df.loc[df['B'].isin(['one','three'])])

Rendimientos

     A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

Si tiene varios valores que desea incluir, colóquelos en un list (o más generalmente, cualquier iterable) y use df.loc:…

df = df.set_index(['B'])
print(df.loc['one'])

Rendimientos

       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12

Si tiene varios valores que desea incluir, colóquelos en un list (o más generalmente, cualquier iterable) y use df.index.isin:…

df.loc[df.index.isin(['one','two'])]

Rendimientos

       A  C   D
B              
one  foo  0   0
one  bar  1   2
two  foo  2   4
two  foo  4   8
two  bar  5  10
one  foo  6  12
3405
unutbu 18 ene. 2019 a las 02:47

Aquí hay un ejemplo simple

from pandas import DataFrame

# Create data set
d = {'Revenue':[100,111,222], 
     'Cost':[333,444,555]}
df = DataFrame(d)


# mask = Return True when the value in column "Revenue" is equal to 111
mask = df['Revenue'] == 111

print mask

# Result:
# 0    False
# 1     True
# 2    False
# Name: Revenue, dtype: bool


# Select * FROM df WHERE Revenue = 111
df[mask]

# Result:
#    Cost    Revenue
# 1  444     111
21
DataByDavid 13 jun. 2013 a las 11:49

Más flexibilidad usando .query con pandas >= 0.25.0:

Respuesta actualizada de agosto de 2019

Desde pandas >= 0.25.0 podemos usar el método query para filtrar marcos de datos con métodos pandas e incluso nombres de columnas que tienen espacios. Normalmente, los espacios en los nombres de columna darían un error, pero ahora podemos resolver eso usando una marca de retroceso (`) ver GitHub:

# Example dataframe
df = pd.DataFrame({'Sender email':['ex@example.com', "reply@shop.com", "buy@shop.com"]})

     Sender email
0  ex@example.com
1  reply@shop.com
2    buy@shop.com

Usando .query con el método str.endswith:

df.query('`Sender email`.str.endswith("@shop.com")')

Salida

     Sender email
1  reply@shop.com
2    buy@shop.com

También podemos usar variables locales prefijándolas con un @ en nuestra consulta:

domain = 'shop.com'
df.query('`Sender email`.str.endswith(@domain)')

Salida

     Sender email
1  reply@shop.com
2    buy@shop.com
18
Erfan 4 ago. 2019 a las 12:59

Para agregar a esta famosa pregunta (aunque un poco tarde): También puede hacer df.groupby('column_name').get_group('column_desired_value').reset_index() para hacer un nuevo marco de datos con una columna específica que tenga un valor particular. P.ej.

import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split()})
print("Original dataframe:")
print(df)

b_is_two_dataframe = pd.DataFrame(df.groupby('B').get_group('two').reset_index()).drop('index', axis = 1) 
#NOTE: the final drop is to remove the extra index column returned by groupby object
print('Sub dataframe where B is two:')
print(b_is_two_dataframe)

Ejecute esto da:

Original dataframe:
     A      B
0  foo    one
1  bar    one
2  foo    two
3  bar  three
4  foo    two
5  bar    two
6  foo    one
7  foo  three
Sub dataframe where B is two:
     A    B
0  foo  two
1  foo  two
2  bar  two
12
TuanDT 18 nov. 2016 a las 12:10

También puedes usar .apply:

df.apply(lambda row: row[df['B'].isin(['one','three'])])

Realmente funciona en filas (es decir, aplica la función a cada fila).

La salida es

   A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

Los resultados son los mismos que los mencionados en @unutbu.

df[[df['B'].isin(['one','three'])]]
5
Vahidn 7 dic. 2018 a las 17:38

Tl; dr

Los pandas equivalentes a

select * from table where column_name = some_value

Es

table[table.column_name == some_value]

Múltiples condiciones:

table[(table.column_name == some_value) | (table.column_name2 == some_value2)]

O

table.query('column_name == some_value | column_name2 == some_value2')

Ejemplo de código

import pandas as pd

# Create data set
d = {'foo':[100, 111, 222], 
     'bar':[333, 444, 555]}
df = pd.DataFrame(d)

# Full dataframe:
df

# Shows:
#    bar   foo 
# 0  333   100
# 1  444   111
# 2  555   222

# Output only the row(s) in df where foo is 222:
df[df.foo == 222]

# Shows:
#    bar  foo
# 2  555  222

En el código anterior, es la línea df[df.foo == 222] la que proporciona las filas según el valor de la columna, 222 en este caso.

Múltiples condiciones también son posibles:

df[(df.foo == 222) | (df.bar == 444)]
#    bar  foo
# 1  444  111
# 2  555  222

Pero en ese momento recomendaría usar la consulta función, ya que es menos detallado y produce el mismo resultado:

df.query('foo == 222 | bar == 444')
270
imolit 28 jun. 2018 a las 15:30

Para seleccionar solo columnas específicas de varias columnas para un valor dado en pandas:

select col_name1, col_name2 from table where column_name = some_value.

Opciones:

df.loc[df['column_name'] == some_value][[col_name1, col_name2]]

O

df.query['column_name' == 'some_value'][[col_name1, col_name2]]
15
firelynx 22 jun. 2018 a las 07:44

Se pueden lograr resultados más rápidos usando numpy.where.

Por ejemplo, con configuración de unubtu -

In [76]: df.iloc[np.where(df.A.values=='foo')]
Out[76]: 
     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Comparaciones de tiempo:

In [68]: %timeit df.iloc[np.where(df.A.values=='foo')]  # fastest
1000 loops, best of 3: 380 µs per loop

In [69]: %timeit df.loc[df['A'] == 'foo']
1000 loops, best of 3: 745 µs per loop

In [71]: %timeit df.loc[df['A'].isin(['foo'])]
1000 loops, best of 3: 562 µs per loop

In [72]: %timeit df[df.A=='foo']
1000 loops, best of 3: 796 µs per loop

In [74]: %timeit df.query('(A=="foo")')  # slowest
1000 loops, best of 3: 1.71 ms per loop
23
Brian Burns 3 oct. 2017 a las 16:17

Encuentro que la sintaxis de las respuestas anteriores es redundante y difícil de recordar. Pandas introdujo el método query() en v0.13 y lo prefiero mucho. Para su pregunta, puede hacer df.query('col == val')

Reproducido de http://pandas.pydata.org/pandas-docs/ versión / 0.17.0 / indexing.html # indexing-query

In [167]: n = 10

In [168]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))

In [169]: df
Out[169]: 
          a         b         c
0  0.687704  0.582314  0.281645
1  0.250846  0.610021  0.420121
2  0.624328  0.401816  0.932146
3  0.011763  0.022921  0.244186
4  0.590198  0.325680  0.890392
5  0.598892  0.296424  0.007312
6  0.634625  0.803069  0.123872
7  0.924168  0.325076  0.303746
8  0.116822  0.364564  0.454607
9  0.986142  0.751953  0.561512

# pure python
In [170]: df[(df.a < df.b) & (df.b < df.c)]
Out[170]: 
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

# query
In [171]: df.query('(a < b) & (b < c)')
Out[171]: 
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

También puede acceder a variables en el entorno anteponiendo un @.

exclude = ('red', 'orange')
df.query('color not in @exclude')
59
fredcallaway 9 feb. 2016 a las 01:36
17071871