Tengo un marco de datos
índice
Calle
Casa
Edificio
1
A B C
20
a
2
A B C
20
b
3
A B C
21
Yaya
4
BCD
2
1
Necesita crear una selección múltiple a partir de este DataFrame:
Si Calle == str_filter;
Si Casa == casa_filtro;
Si el edificio == build_filter Y si el edificio no es NULL;
Ya probé df[(df['Street'] == str_filter) & (df['Casa'] == house_filter) & ((df['Edificio'] == build_filter) & (pd.notnull(df['Edificio'])))
Pero no conduce a un resultado que particularmente quiera ver. Tengo que verificar si el valor del edificio no es NaN y, si es verdadero, seleccionar la fila con el número de edificio determinado. Sin embargo, también quiero seleccionar la fila si tiene un valor NaN para el edificio pero también cumple con otros criterios.
Otra idea fue crear listas parar el conjunto de valores de filtro y el conjunto de estos valores que cumplen con los criterios de pd.notnull:
filter_values = [str_filter, house_filter, build_filter]
notnull_values = [pd.notnull(entry) for entry in filter_values]
Este no cumple con los criterios de rendimiento, porque tengo un DataFrame extremadamente grande y la creación de listas adicionales con filtrado adicional conducirá a un rendimiento superior. La posible solución puede estar en la función df.loc, pero no sé cómo implementarla.
Para resumir, el problema es el siguiente: ¿Cómo crear selección múltiple en pandas con condiciones para valores NaN?
UPD: Parece que la función que tengo que usar es df[... & (df['Building'] == 'a' if pd.notnull(df['Building']))] usando una analogía con el truco de aplicación lambda
¿Tiene un ejemplo de qué tipo de filtro desea aplicar? Mi intuición me dice que esto se podría solucionar con mascarillas.
- Oddaspa
28/03/2021 a las 15:40
@Oddaspa ¡Claro! Quiero encontrar todos los duplicados en determinadas columnas, pero parece que df.duplicated no funciona para entradas con valores NaN. Entonces, bajo filtros me refiero a ciertos valores, es decir, df[(df['Building'] == 'a') & (pd.notnull(df['Edificio'])))]
-velastim
28/03/2021 a las 15:46
Veo que actualizaste la pregunta. ¿Probaste mi respuesta?
- Oddaspa
28/03/2021 a las 16:18
------------------------------------
Como dijiste en un comentario que también tenías problemas con los duplicados, agregué una opción para eliminarlos.
Recreé su conjunto de datos con esto y agregué un duplicado.
df = pd.DataFrame({
"Street" : ["ABC", "ABC", "ABC", "BCD", "ABC"],
"House" : [20, 20, 21, 2, 21],
"Building" : ['a', 'b', np.NaN, 1, np.NaN]
})
Para eliminar duplicados de su conjunto de datos, simplemente puede ejecutar este bloque:
df = df.drop_duplicates()
Estoy asumiendoque su filtro podría ser una lista blanca de cadenas o números que desea incluir en su conjunto de datos final. Por eso me tomé la libertad de definir un filtro como este:
street_filter = ["ABC", "BCD"]
Para limpiar el conjunto de datos, puedes utilizar este método:
def get_mask(df, street_filter, house_filter, building_filter):
not_na_mask = df['Building'].notna()
# hopefully smaller df to query
df = df[not_na_mask]
street_mask = df['Street'].apply(lambda x: x in street_filter)
df = df[street_mask]
house_mask = df['House'].apply(lambda x: x in house_filter)
df = df[house_mask]
building_mask = df['Building'].apply(lambda x: x in building_filter)
return df[building_mask]
Ejemplo
street_filter = ["ABC", "BCD"]
house_filter = [20, 21]
building_filter = ["a"]
get_mask(df, street_filter, house_filter, building_filter)
Street House Building
0 ABC 20 a
------------------------------------
Una forma bastante sencilla de hacerlo sería esta:
if df[df['Building'].isnull()].empty:
df[df['Street'] == str_filter][df['House'] == house_filter][df['Building'] == build_filter]
else:
df[df['Street'] == str_filter][df['House'] == house_filter][df['Building'].isnull()]
¿No estoy seguro de si esto satisfaría sus requisitos de rendimiento?
7
Probé tu código. Funciona perfecto para múltiples condiciones, pero falla cuando intento seleccionar filas con NaN en el campo Edificio
-velastim
28/03/2021 a las 17:05
¿Entonces quieres que el campo Edificio sea igual a NaN? Pensé que querías excluir los valores de NaN. @sailestim
- Tetalesti
28/03/2021 a las 17:07
Recientemente actualicé el código. Solo lo digo en caso de que solo hayas probado el código de mi respuesta anterior.
- Tetalesti
28/03/2021 a las 17:08
¡Gracias! Probé el último. Entonces, todo lo que quiero es solo una simple selección de subconjunto de marco de datos de valores iguales, incluidos los valores de NaN. Tomando mi ejemplo, quiero seleccionar la tercera fila. Si no hubiera ningún valor NaN en el campo Edificio, usaría df[df['Building'] == 'a']. Pero no funciona con NaN, así que tengo que usar algún tipo de excepción como mi UPD en elpregunta: df[(df['Edificio'] == 'a' if pd.notnull(df['Edificio']) else df[' Edificio'] == math.nan ]
-velastim
28/03/2021 a las 17:17
1
Bien, según tengo entendido, desea seleccionar todos los valores NaN en el edificio, pero si no hay ninguno, entonces desea seleccionar del edificio y luego seleccionar dónde [edificio == "Alguna cadena"]. Trabajaré en una respuesta para usted. Tardaré unos minutos.
- Tetalesti
28/03/2021 a las 17:26