¿Cómo puedo seleccionar filas de un DataFrame según los valores en alguna columna en Pandas?
En SQL, usaría:
SELECT * FROM table WHERE column_name = some_valueTraté de mirar la documentación de Pandas, pero no encontré la respuesta de inmediato.
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 iterable, some_values , use isin :
df.loc[df['column_name'].isin(some_values)] Combine múltiples condiciones con & :
df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)] Tenga en cuenta los paréntesis. Debido a lasreglas de precedencia de operadores de Python, & enlaza más estrechamente 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'] <= Bse analiza como
df['column_name'] >= (A & df['column_name']) <= Blo que da como resultado un valor de Verdad de una Serie es un error ambiguo .
Para seleccionar filas cuyo valor de columna no es igual a some_value , use != :
df.loc[df['column_name'] != some_value] isin devuelve una Serie booleana, por lo que para seleccionar filas cuyo valor no está en some_values , niega 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) # ABCD # 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
ABCD 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, póngalos en una lista (o más generalmente, cualquier iterable) y use isin :
print(df.loc[df['B'].isin(['one','three'])])rendimientos
ABCD 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 Tenga en cuenta, sin embargo, que si desea hacer esto muchas veces, es más eficiente crear primero un índice y luego usar df.loc :
df = df.set_index(['B']) print(df.loc['one'])rendimientos
ACD B one foo 0 0 one bar 1 2 one foo 6 12 o, para incluir varios valores del índice, use df.index.isin :
df.loc[df.index.isin(['one','two'])]rendimientos
ACD B one foo 0 0 one bar 1 2 two foo 2 4 two foo 4 8 two bar 5 10 one foo 6 12Aquí 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 111Los pandas equivalentes a
select * from table where column_name = some_valuees
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') 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 da 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 222Pero en ese momento recomendaría usar la función de consulta , ya que es menos detallada y produce el mismo resultado:
df.query('foo == 222 | bar == 444')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 loc :
df.loc[df['column_name'] == some_value, [col_name1, col_name2]] oquery :
df.query('column_name == some_value')[[col_name1, col_name2]]Se pueden lograr resultados más rápidos usando numpy.where .
Por ejemplo, con la configuración de unubtu :
In [76]: df.iloc[np.where(df.A.values=='foo')] Out[76]: ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14Comparaciones 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 loopPara agregar a esta famosa pregunta (aunque un poco demasiado tarde): también puede hacer df.groupby('column_name').get_group('column_desired_value').reset_index() para crear 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)Ejecutar esto da:
Original dataframe: AB 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: AB 0 foo two 1 foo two 2 bar twoEncuentro 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. Para su pregunta, podría hacer df.query('col == val')
Reproducido de http://pandas.pydata.org/pandas-docs/version/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]: abc 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]: abc 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]: abc 3 0.011763 0.022921 0.244186 8 0.116822 0.364564 0.454607 También puede acceder a las variables en el entorno anteponiendo una @ .
exclude = ('red', 'orange') df.query('color not in @exclude')En versiones más nuevas de Pandas, inspiradas en la documentación ( Visualización de datos ):
df[df["colume_name"] == some_value] #Scalar, True/False.. df[df["colume_name"] == "some_value"] #String Combine varias condiciones poniendo la cláusula entre paréntesis, () y combinándolas con & y | (y/o). Me gusta esto:
df[(df["colume_name"] == "some_value1") & (pd[pd["colume_name"] == "some_value2"])]Otros filtros
pandas.notna(df["colume_name"]) == True # Not NaN df['colume_name'].str.contains("text") # Search for "text" df['colume_name'].str.lower().str.contains("text") # Search for "text", after converting to lowercaseTambién puedes usar .apply:
df.apply(lambda row: row[df['B'].isin(['one','three'])])En realidad, funciona por filas (es decir, aplica la función a cada fila).
la salida es
ABCD 0 foo one 0 0 1 bar one 1 2 3 bar three 3 6 6 foo one 6 12 7 foo three 7 14Los resultados son los mismos que los mencionados por @unutbu
df[[df['B'].isin(['one','three'])]].query con pandas >= 0.25.0:Respuesta actualizada de agosto de 2019
Dado que pandas >= 0.25.0, podemos usar el método de query para filtrar marcos de datos con métodos de pandas e incluso nombres de columnas que tienen espacios. Normalmente, los espacios en los nombres de las columnas darían un error, pero ahora podemos resolverlo usando un acento grave (`) - vea 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")')Producción
Sender email 1 reply@shop.com 2 buy@shop.com También podemos usar variables locales anteponiéndolas con un @ en nuestra consulta:
domain = 'shop.com' df.query('`Sender email`.str.endswith(@domain)')Producción
Sender email 1 reply@shop.com 2 buy@shop.comSi desea realizar consultas en su marco de datos repetidamente y la velocidad es importante para usted, lo mejor es convertir su marco de datos en diccionario y, al hacerlo, puede realizar consultas miles de veces más rápido.
my_df = df.set_index(column_name) my_dict = my_df.to_dict('index')Después de hacer el diccionario my_dict, puede pasar por:
if some_value in my_dict.keys(): my_result = my_dict[some_value]Si tiene valores duplicados en column_name, no puede crear un diccionario. pero puedes usar:
my_result = my_df.loc[some_value]Grandes respuestas. Solo que, cuando el tamaño del marco de datos se acerca al millón de filas , muchos de los métodos tienden a tardar años cuando se usa df[df['col']==val] . Quería tener todos los valores posibles de "otra_columna" que correspondan a valores específicos en "alguna_columna" (en este caso en un diccionario). Esto funcionó y rápido.
s=datetime.datetime.now() my_dict={} for i, my_key in enumerate(df['some_column'].values): if i%100==0: print(i) # to see the progress if my_key not in my_dict.keys(): my_dict[my_key]={} my_dict[my_key]['values']=[df.iloc[i]['another_column']] else: my_dict[my_key]['values'].append(df.iloc[i]['another_column']) e=datetime.datetime.now() print('operation took '+str(es)+' seconds')```