Quiero aplicar mi función personalizada (que utiliza una escalera si-else) a estos seis columnas ( ERI_Hispanic
, ERI_AmerInd_AKNatv
, ERI_Asian
, ERI_Black_Afr.Amer
, ERI_HI_PacIsl
, ERI_White
) en cada fila de mi trama de datos.
He probado diferentes métodos de otras preguntas, pero parece que todavía no puedo encontrar la respuesta correcta para mi problema. La parte crítica de esto es que si la persona se cuenta como hispana, no se puede contar como otra cosa. Incluso si tienen un "1" en otra columna de etnia, todavía se cuentan como hispanos, no dos o más razas. Del mismo modo, si la suma de todas las columnas ERI es mayor que 1, se cuentan como dos o más razas y no se pueden contar como una etnia única (excepto para los hispanos). Esperemos que esto tenga sentido. Cualquier ayuda será apreciada.
Es casi como hacer un ciclo for a través de cada fila y si cada registro cumple con un criterio, se agregan a una lista y se eliminan del original.
Del siguiente marco de datos necesito calcular una nueva columna basada en la siguiente especificación en SQL:
========================= CRITERIOS ======================== =======
IF [ERI_Hispanic] = 1 THEN RETURN “Hispanic”
ELSE IF SUM([ERI_AmerInd_AKNatv] + [ERI_Asian] + [ERI_Black_Afr.Amer] + [ERI_HI_PacIsl] + [ERI_White]) > 1 THEN RETURN “Two or More”
ELSE IF [ERI_AmerInd_AKNatv] = 1 THEN RETURN “A/I AK Native”
ELSE IF [ERI_Asian] = 1 THEN RETURN “Asian”
ELSE IF [ERI_Black_Afr.Amer] = 1 THEN RETURN “Black/AA”
ELSE IF [ERI_HI_PacIsl] = 1 THEN RETURN “Haw/Pac Isl.”
ELSE IF [ERI_White] = 1 THEN RETURN “White”
Comentario: Si la bandera ERI para hispanos es verdadera (1), el empleado se clasifica como "hispano"
Comentario: si más de 1 bandera ERI no hispana es verdadera, devuelva "Dos o más"
====================== DATAFRAME ===========================
lname fname rno_cd eri_afr_amer eri_asian eri_hawaiian eri_hispanic eri_nat_amer eri_white rno_defined
0 MOST JEFF E 0 0 0 0 0 1 White
1 CRUISE TOM E 0 0 0 1 0 0 White
2 DEPP JOHNNY 0 0 0 0 0 1 Unknown
3 DICAP LEO 0 0 0 0 0 1 Unknown
4 BRANDO MARLON E 0 0 0 0 0 0 White
5 HANKS TOM 0 0 0 0 0 1 Unknown
6 DENIRO ROBERT E 0 1 0 0 0 1 White
7 PACINO AL E 0 0 0 0 0 1 White
8 WILLIAMS ROBIN E 0 0 1 0 0 0 White
9 EASTWOOD CLINT E 0 0 0 0 0 1 White
Respuestas:
OK, dos pasos para esto, primero es escribir una función que haga la traducción que deseas, he reunido un ejemplo basado en tu pseudocódigo:
Es posible que desee repasar esto, pero parece ser el truco: tenga en cuenta que el parámetro que entra en la función se considera un objeto Serie etiquetado como "fila".
Luego, use la función de aplicar en pandas para aplicar la función, por ejemplo
Tenga en cuenta el eje = 1 especificador, eso significa que la aplicación se realiza en una fila, en lugar de un nivel de columna. Los resultados están aquí:
Si está satisfecho con esos resultados, ejecútelos nuevamente, guardando los resultados en una nueva columna en su marco de datos original.
El marco de datos resultante tiene este aspecto (desplácese hacia la derecha para ver la nueva columna):
fuente
df.apply(label_race, axis=1)
return 'Other'
línea final a lareturn row['rno_defined']
que debería sustituya el valor de esa columna en aquellos casos en que el conjunto de sentencias if / then no encuentre una coincidencia (es decir, donde actualmente, ve 'Otro')df.apply(lambda row: label_race (row),axis=1)
todf.apply(label_race, axis=1)
Dado que este es el primer resultado de Google para 'pandas nueva columna de otros', aquí hay un ejemplo simple:
Si obtiene el
SettingWithCopyWarning
puede hacerlo de esta manera también:Fuente: https://stackoverflow.com/a/12555510/243392
Y si el nombre de su columna incluye espacios, puede usar una sintaxis como esta:
Y aquí está la documentación para aplicar y asignar .
fuente
SettingWithCopyWarning
cuando lo hagodf['c'] = df.apply(lambda row: row.a + row.b, axis=1)
¿Es un problema real aquí, o no debería preocuparme?Las respuestas anteriores son perfectamente válidas, pero existe una solución vectorizada, en forma de
numpy.select
. Esto le permite definir condiciones, luego definir salidas para esas condiciones, mucho más eficientemente que usarapply
:Primero, defina las condiciones:
Ahora, defina las salidas correspondientes:
Finalmente, usando
numpy.select
:¿Por qué debería
numpy.select
ser usadoapply
? Aquí hay algunas comprobaciones de rendimiento:El uso
numpy.select
nos proporciona un rendimiento enormemente mejorado, y la discrepancia solo aumentará a medida que crezcan los datos.fuente
.apply()
toma una función como primer parámetro; Pase lalabel_race
función de la siguiente manera:No necesita hacer una función lambda para pasar una función.
fuente
prueba esto,
O / P:
usar en
.loc
lugar deapply
.Mejora la vectorización.
.loc
funciona de manera simple, enmascarar filas según la condición, aplicar valores a las filas congeladas.para más detalles visite, .loc docs
Métricas de rendimiento:
Respuesta aceptada:
Mi respuesta propuesta:
fuente