Filtrar un dataframe de pandas usando valores de un dict.

Necesito filtrar un dataframe con un dict, construido con la clave siendo el nombre de la columna y el valor siendo el valor que quiero filtrar:

filter_v = {'A':1, 'B':0, 'C':'This is right'} # this would be the normal approach df[(df['A'] == 1) & (df['B'] ==0)& (df['C'] == 'This is right')] 

Pero quiero hacer algo en las líneas.

 for column, value in filter_v.items(): df[df[column] == value] 

pero esto filtrará el cuadro de datos varias veces, un valor a la vez, y no aplicará todos los filtros al mismo tiempo. ¿Hay una manera de hacerlo programáticamente?

EDITAR: un ejemplo:

 df1 = pd.DataFrame({'A':[1,0,1,1, np.nan], 'B':[1,1,1,0,1], 'C':['right','right','wrong','right', 'right'],'D':[1,2,2,3,4]}) filter_v = {'A':1, 'B':0, 'C':'right'} df1.loc[df1[filter_v.keys()].isin(filter_v.values()).all(axis=1), :] 

da

  ABCD 0 1 1 right 1 1 0 1 right 2 3 1 0 right 3 

pero el resultado esperado fue

  ABCD 3 1 0 right 3 

solo el último debe ser seleccionado.

IIUC, deberías poder hacer algo como esto:

 >>> df1.loc[(df1[list(filter_v)] == pd.Series(filter_v)).all(axis=1)] ABCD 3 1 0 right 3 

Esto funciona haciendo una serie para comparar contra:

 >>> pd.Series(filter_v) A 1 B 0 C right dtype: object 

Seleccionando la parte correspondiente de df1 :

 >>> df1[list(filter_v)] ACB 0 1 right 1 1 0 right 1 2 1 wrong 1 3 1 right 0 4 NaN right 1 

Encontrando donde coinciden:

 >>> df1[list(filter_v)] == pd.Series(filter_v) ABC 0 True False True 1 False False True 2 True False False 3 True True True 4 False False True 

Encontrando donde todos coinciden:

 >>> (df1[list(filter_v)] == pd.Series(filter_v)).all(axis=1) 0 False 1 False 2 False 3 True 4 False dtype: bool 

Y finalmente usando esto para indexar en df1:

 >>> df1.loc[(df1[list(filter_v)] == pd.Series(filter_v)).all(axis=1)] ABCD 3 1 0 right 3 

Aquí hay una forma de hacerlo:

 df.loc[df[filter_v.keys()].isin(filter_v.values()).all(axis=1), :] 

ACTUALIZAR:

Con los valores iguales en todas las columnas, podrías hacer algo como esto:

 # Create your filtering function: def filter_dict(df, dic): return df[df[dic.keys()].apply( lambda x: x.equals(pd.Series(dic.values(), index=x.index, name=x.name)), asix=1)] # Use it on your DataFrame: filter_dict(df1, filter_v) 

Cuyos rendimientos:

  ABCD 3 1 0 right 3 

Si es algo que haces con frecuencia, puedes llegar a parchar DataFrame para acceder fácilmente a este filtro:

 pd.DataFrame.filter_dict_ = filter_dict 

Y luego use este filtro como este:

 df1.filter_dict_(filter_v) 

Lo que daría el mismo resultado.

PERO , no es la forma correcta de hacerlo, claramente. Yo usaría el enfoque de DSM.

Aquí hay otra manera:

 filterSeries = pd.Series(np.ones(df.shape[0],dtype=bool)) for column, value in filter_v.items(): filterSeries = ((df[column] == value) & filterSeries) 

Esto da:

 >>> df[filterSeries] ABCD 3 1 0 right 3 

Para python2, eso está bien en la respuesta de @primer. Pero debes tener cuidado en Python3 debido a dict_keys . Por ejemplo,

 >> df.loc[df[filter_v.keys()].isin(filter_v.values()).all(axis=1), :] >> TypeError: unhashable type: 'dict_keys' 

La forma correcta de Python3:

 df.loc[df[list(filter_v.keys())].isin(list(filter_v.values())).all(axis=1), :]