tablas para leer funciones filtrar datos como python pandas

python - filtrar - funciones de pandas para leer datos a tablas



pandas: filtrar filas de DataFrame con el encadenamiento del operador (14)

La mayoría de las operaciones en pandas se pueden realizar con el encadenamiento de operadores ( groupby , aggregate , apply , etc.), pero la única forma que he encontrado para filtrar filas es a través de la indexación de corchetes normal

df_filtered = df[df[''column''] == value]

Esto no es atractivo ya que requiere que asigne df a una variable antes de poder filtrar por sus valores. ¿Hay algo más parecido a lo siguiente?

df_filtered = df.mask(lambda x: x[''column''] == value)


Esto no es atractivo ya que requiere que asigne df a una variable antes de poder filtrar por sus valores.

df[df["column_name"] != 5].groupby("other_column_name")

Parece funcionar: también se puede encadenar el operador [] . Tal vez lo agregaron desde que hiciste la pregunta.


Desde la versión 0.18.1, el método .loc acepta un llamable para la selección. Junto con las funciones lambda, puede crear filtros chainable muy flexibles:

import numpy as np import pandas as pd df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list(''ABCD'')) df.loc[lambda df: df.A == 80] # equivalent to df[df.A == 80] but chainable df.sort_values(''A'').loc[lambda df: df.A > 80].loc[lambda df: df.B > df.A]

Si todo lo que está haciendo es filtrar, también puede omitir .loc .


Esta solución es más complicada en términos de implementación, pero me parece mucho más limpia en términos de uso, y ciertamente es más general que las otras propuestas.

https://github.com/toobaz/generic_utils/blob/master/generic_utils/pandas/where.py

No es necesario descargar el repositorio completo: guardar el archivo y hacerlo

from where import where as W

debería bastar Entonces lo usas así:

df = pd.DataFrame([[1, 2, True], [3, 4, False], [5, 7, True]], index=range(3), columns=[''a'', ''b'', ''c'']) # On specific column: print(df.loc[W[''a''] > 2]) print(df.loc[-W[''a''] == W[''b'']]) print(df.loc[~W[''c'']]) # On entire - or subset of a - DataFrame: print(df.loc[W.sum(axis=1) > 3]) print(df.loc[W[[''a'', ''b'']].diff(axis=1)[''b''] > 1])

Un ejemplo de uso un poco menos estúpido:

data = pd.read_csv(''ugly_db.csv'').loc[~(W == ''$null$'').any(axis=1)]

Por cierto: incluso en el caso de que solo esté utilizando cols booleanos,

df.loc[W[''cond1'']].loc[W[''cond2'']]

puede ser mucho más eficiente que

df.loc[W[''cond1''] & W[''cond2'']]

porque evalúa cond2 solo donde cond1 es True .

DESCARGO DE RESPONSABILIDAD: Primero di esta respuesta en elsewhere porque no había visto esto.


La respuesta de @lodagro es genial. Lo extendería generalizando la función de máscara como:

def mask(df, f): return df[f(df)]

Entonces puedes hacer cosas como:

df.mask(lambda x: x[0] < 0).mask(lambda x: x[1] > 0)


Los filtros se pueden encadenar usando una query Pandas:

df = pd.DataFrame( np.random.randn(30,3), columns = [''a'',''b'',''c'']) df_filtered = df.query(''a>0'').query(''0<b<2'')

Los filtros también se pueden combinar en una sola consulta:

df_filtered = df.query(''a>0 and 0<b<2'')


Mi respuesta es similar a las otras. Si no desea crear una nueva función, puede usar lo que pandas ya ha definido para usted. Utilice el método de la tubería.

df.pipe(lambda d: d[d[''column''] == value])


No estoy completamente seguro de lo que quiere, y su última línea de código tampoco ayuda, pero de todos modos:

El filtrado "encadenado" se realiza "encadenando" los criterios en el índice booleano.

In [96]: df Out[96]: A B C D a 1 4 9 1 b 4 5 0 2 c 5 5 1 0 d 1 3 9 6 In [99]: df[(df.A == 1) & (df.D == 6)] Out[99]: A B C D d 1 3 9 6

Si desea encadenar métodos, puede agregar su propio método de máscara y usar ese.

In [90]: def mask(df, key, value): ....: return df[df[key] == value] ....: In [92]: pandas.DataFrame.mask = mask In [93]: df = pandas.DataFrame(np.random.randint(0, 10, (4,4)), index=list(''abcd''), columns=list(''ABCD'')) In [95]: df.ix[''d'',''A''] = df.ix[''a'', ''A''] In [96]: df Out[96]: A B C D a 1 4 9 1 b 4 5 0 2 c 5 5 1 0 d 1 3 9 6 In [97]: df.mask(''A'', 1) Out[97]: A B C D a 1 4 9 1 d 1 3 9 6 In [98]: df.mask(''A'', 1).mask(''D'', 6) Out[98]: A B C D d 1 3 9 6


Ofrezco esto para ejemplos adicionales. Esta es la misma respuesta que https://.com/a/28159296/

Añadiré otras ediciones para hacer esta publicación más útil.

query
query fue hecha exactamente para este propósito. Considere el df marco de datos

import pandas as pd import numpy as np np.random.seed([3,1415]) df = pd.DataFrame( np.random.randint(10, size=(10, 5)), columns=list(''ABCDE'') ) df A B C D E 0 0 2 7 3 8 1 7 0 6 8 6 2 0 2 0 4 9 3 7 3 2 4 3 4 3 6 7 7 4 5 5 3 7 5 9 6 8 7 6 4 7 7 6 2 6 6 5 8 2 8 7 5 8 9 4 7 6 1 5

Usemos la query para filtrar todas las filas donde D > B

df.query(''D > B'') A B C D E 0 0 2 7 3 8 1 7 0 6 8 6 2 0 2 0 4 9 3 7 3 2 4 3 4 3 6 7 7 4 5 5 3 7 5 9 7 6 2 6 6 5

Que encadenamos

df.query(''D > B'').query(''C > B'') # equivalent to # df.query(''D > B and C > B'') # but defeats the purpose of demonstrating chaining A B C D E 0 0 2 7 3 8 1 7 0 6 8 6 4 3 6 7 7 4 5 5 3 7 5 9 7 6 2 6 6 5


Si configura sus columnas para buscar como índices, entonces puede usar DataFrame.xs() para tomar una sección transversal. Esto no es tan versátil como responde la query , pero puede ser útil en algunas situaciones.

import pandas as pd import numpy as np np.random.seed([3,1415]) df = pd.DataFrame( np.random.randint(3, size=(10, 5)), columns=list(''ABCDE'') ) df # Out[55]: # A B C D E # 0 0 2 2 2 2 # 1 1 1 2 0 2 # 2 0 2 0 0 2 # 3 0 2 2 0 1 # 4 0 1 1 2 0 # 5 0 0 0 1 2 # 6 1 0 1 1 1 # 7 0 0 2 0 2 # 8 2 2 2 2 2 # 9 1 2 0 2 1 df.set_index([''A'', ''D'']).xs([0, 2]).reset_index() # Out[57]: # A D B C E # 0 0 2 2 2 2 # 1 0 2 1 1 0


Si desea aplicar todas las máscaras booleanas comunes, así como una máscara de propósito general, puede colocar lo siguiente en un archivo y luego asignarlos a todos de la siguiente manera:

pd.DataFrame = apply_masks()

Uso:

A = pd.DataFrame(np.random.randn(4, 4), columns=["A", "B", "C", "D"]) A.le_mask("A", 0.7).ge_mask("B", 0.2)... (May be repeated as necessary

Es un poco intrincado, pero puede hacer las cosas un poco más limpias si está continuamente cortando y cambiando conjuntos de datos según los filtros. También hay un filtro de propósito general adaptado de Daniel Velkov arriba en la función gen_mask que puede usar con las funciones lambda o si lo desea.

Archivo a guardar (uso masks.py):

import pandas as pd def eq_mask(df, key, value): return df[df[key] == value] def ge_mask(df, key, value): return df[df[key] >= value] def gt_mask(df, key, value): return df[df[key] > value] def le_mask(df, key, value): return df[df[key] <= value] def lt_mask(df, key, value): return df[df[key] < value] def ne_mask(df, key, value): return df[df[key] != value] def gen_mask(df, f): return df[f(df)] def apply_masks(): pd.DataFrame.eq_mask = eq_mask pd.DataFrame.ge_mask = ge_mask pd.DataFrame.gt_mask = gt_mask pd.DataFrame.le_mask = le_mask pd.DataFrame.lt_mask = lt_mask pd.DataFrame.ne_mask = ne_mask pd.DataFrame.gen_mask = gen_mask return pd.DataFrame if __name__ == ''__main__'': pass


Solo desea agregar una demostración usando loc para filtrar no solo por filas sino también por columnas y algunos méritos a la operación encadenada.

El siguiente código puede filtrar las filas por valor.

df_filtered = df.loc[df[''column''] == value]

Al modificarlo un poco puedes filtrar las columnas también.

df_filtered = df.loc[df[''column''] == value, [''year'', ''column'']]

Entonces, ¿por qué queremos un método encadenado? La respuesta es que es fácil de leer si tiene muchas operaciones. Por ejemplo,

res = df/ .loc[df[''station'']==''USA'', [''TEMP'', ''RF'']]/ .groupby(''year'')/ .agg(np.nanmean)


También puede aprovechar la biblioteca numpy para operaciones lógicas. Es bastante rápido.

df[np.logical_and(df[''A''] == 1 ,df[''B''] == 6)]


Tenía la misma pregunta, excepto que quería combinar los criterios en una condición OR. El formato dado por Wouter Overmeire combina los criterios en una condición AND tal que ambos deben cumplirse:

In [96]: df Out[96]: A B C D a 1 4 9 1 b 4 5 0 2 c 5 5 1 0 d 1 3 9 6 In [99]: df[(df.A == 1) & (df.D == 6)] Out[99]: A B C D d 1 3 9 6

Pero descubrí que, si envuelve cada condición en (... == True) y une los criterios con una canalización, los criterios se combinan en una condición OR, satisfechos siempre que alguno de ellos sea verdadero:

df[((df.A==1) == True) | ((df.D==6) == True)]


pandas ofrece dos alternativas a la respuesta de Wouter Overmeire que no requieren ninguna anulación. Uno es .loc[.] Con una llamada, como en

df_filtered = df.loc[lambda x: x[''column''] == value]

el otro es .pipe() , como en

df_filtered = df.pipe(lambda x: x[''column''] == value)