tutorial tablas seleccionar notebook filtrar español documentacion datos curso columnas python pandas dataframe filter exec

python - tablas - Filtrando dinámicamente un marco de datos pandas



seleccionar columnas en pandas (2)

Si estás tratando de construir una consulta dinámica, hay formas más fáciles. Aquí hay uno que usa una lista de comprensión y str.join :

query = '' & ''.join([''{}>{}''.format(k, v) for k, v in limits_dic.items()])

O, usando f cuerdas con python-3.6 +,

query = '' & ''.join([f''{k}>{v}'' for k, v in limits_dic.items()])

print(query) ''A>0 & C>-1 & B>2''

Pase la cadena de consulta a df.query , está destinada a este propósito:

out = df.query(query) print(out) A B C 1 2 5 2 2 10 3 1 4 3 6 2

También puede usar df.eval si desea obtener una máscara booleana para su consulta, y luego la indexación se vuelve sencilla después de eso:

mask = df.eval(query) print(mask) 0 False 1 True 2 True 3 False 4 True dtype: bool out = df[mask] print(out) A B C 1 2 5 2 2 10 3 1 4 3 6 2

Cadena de datos

Si necesita consultar columnas que usan datos de cadena, el código anterior necesitará una ligera modificación.

Considere (datos de esta respuesta ):

df = pd.DataFrame({''gender'':list(''MMMFFF''), ''height'':[4,5,4,5,5,4], ''age'':[70,80,90,40,2,3]}) print (df) gender height age 0 M 4 70 1 M 5 80 2 M 4 90 3 F 5 40 4 F 5 2 5 F 4 3

Y una lista de columnas, operadores y valores:

column = [''height'', ''age'', ''gender''] equal = [''>'', ''>'', ''==''] condition = [1.68, 20, ''F'']

La modificación apropiada aquí es:

query = '' & ''.join(f''{i} {j} {repr(k)}'' for i, j, k in zip(column, equal, condition)) df.query(query) age gender height 3 40 F 5

Para obtener información sobre la familia de funciones pd.eval() , sus características y casos de uso, visite la Evaluación de Expresión Dinámica en pandas usando pd.eval () .

Estoy tratando de filtrar un marco de datos de pandas utilizando umbrales para tres columnas

import pandas as pd df = pd.DataFrame({"A" : [6, 2, 10, -5, 3], "B" : [2, 5, 3, 2, 6], "C" : [-5, 2, 1, 8, 2]}) df = df.loc[(df.A > 0) & (df.B > 2) & (df.C > -1)].reset_index(drop = True) df A B C 0 2 5 2 1 10 3 1 2 3 6 2

Sin embargo, quiero hacer esto dentro de una función donde se me dan los nombres de las columnas y sus umbrales en un diccionario. Aquí está mi primer intento que funciona bien. Esencialmente estoy poniendo el filtro dentro de la variable cond y simplemente ejecutarlo:

df = pd.DataFrame({"A" : [6, 2, 10, -5, 3], "B" : [2, 5, 3, 2, 6], "C" : [-5, 2, 1, 8, 2]}) limits_dic = {"A" : 0, "B" : 2, "C" : -1} cond = "df = df.loc[" for key in limits_dic.keys(): cond += "(df." + key + " > " + str(limits_dic[key])+ ") & " cond = cond[:-2] + "].reset_index(drop = True)" exec(cond) df A B C 0 2 5 2 1 10 3 1 2 3 6 2

Ahora, finalmente puse todo dentro de una función y deja de funcionar (¡tal vez a la función exec no le gusta que se use dentro de una función!):

df = pd.DataFrame({"A" : [6, 2, 10, -5, 3], "B" : [2, 5, 3, 2, 6], "C" : [-5, 2, 1, 8, 2]}) limits_dic = {"A" : 0, "B" : 2, "C" : -1} def filtering(df, limits_dic): cond = "df = df.loc[" for key in limits_dic.keys(): cond += "(df." + key + " > " + str(limits_dic[key])+ ") & " cond = cond[:-2] + "].reset_index(drop = True)" exec(cond) return(df) df = filtering(df, limits_dic) df A B C 0 6 2 -5 1 2 5 2 2 10 3 1 3 -5 2 8 4 3 6 2

Sé que la función exec actúa de manera diferente cuando se usa dentro de una función, pero no estaba seguro de cómo abordar el problema. Además, me pregunto si debe haber una forma más elegante de definir una función para realizar el filtrado a partir de dos entradas: 1) df y 2) limits_dic = {"A" : 0, "B" : 2, "C" : -1} . Apreciaría cualquier pensamiento sobre esto.


Una alternativa a la versión de @coldspeed:

conditions = None for key, val in limit_dic.items(): cond = df[key] > val if conditions is None: conditions = cond else: conditions = conditions & cond print(df[conditions])