Quero aplicar minha função personalizada (ele usa uma escada de if-else) para estes seis colunas ( ERI_Hispanic
, ERI_AmerInd_AKNatv
, ERI_Asian
, ERI_Black_Afr.Amer
, ERI_HI_PacIsl
, ERI_White
) em cada linha da minha trama de dados.
Tentei métodos diferentes de outras perguntas, mas ainda não consigo encontrar a resposta certa para o meu problema. A parte crítica disso é que, se a pessoa é contada como hispânica, ela não pode ser contada como qualquer outra coisa. Mesmo que eles tenham um "1" em outra coluna de etnia, eles ainda são contados como hispânicos, não como duas ou mais raças. Da mesma forma, se a soma de todas as colunas da ERI for maior que 1, elas serão contadas como duas ou mais raças e não poderão ser contadas como uma etnia única (exceto para hispânicas). Espero que isso faça sentido. Qualquer ajuda será muito apreciada.
É quase como fazer um loop for em cada linha e, se cada registro atender a um critério, eles serão adicionados a uma lista e eliminados do original.
No dataframe abaixo, preciso calcular uma nova coluna com base nas seguintes especificações no SQL:
========================= CRITÉRIOS ======================== =======
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”
Comentário: se o sinalizador do ERI para hispânico for verdadeiro (1), o funcionário será classificado como "hispânico"
Comentário: se mais de 1 bandeira ERI não hispânica for verdadeira, retorne "Dois ou mais"
====================== 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
Respostas:
OK, duas etapas para isso - primeiro é escrever uma função que faça a tradução desejada - juntei um exemplo com base no seu pseudo-código:
Você pode revisar isso, mas parece fazer o truque - observe que o parâmetro que entra na função é considerado um objeto da série chamado "linha".
Em seguida, use a função aplicar nos pandas para aplicar a função - por exemplo
Observe o especificador axis = 1, isso significa que o aplicativo é feito em uma linha, em vez de no nível da coluna. Os resultados estão aqui:
Se você estiver satisfeito com esses resultados, execute-o novamente, salvando os resultados em uma nova coluna no quadro de dados original.
O quadro de dados resultante tem esta aparência (role para a direita para ver a nova coluna):
fonte
df.apply(label_race, axis=1)
return 'Other'
linha final para areturn row['rno_defined']
qual deve substitua o valor dessa coluna nos casos em que o conjunto de instruções if / then não encontra uma correspondência (ou seja, onde atualmente, você vê 'Outros').df.apply(lambda row: label_race (row),axis=1)
paradf.apply(label_race, axis=1)
Como este é o primeiro resultado do Google para 'pandas nova coluna de outros', aqui está um exemplo simples:
Se você receber,
SettingWithCopyWarning
poderá fazê-lo desta maneira também:Fonte: https://stackoverflow.com/a/12555510/243392
E se o nome da sua coluna incluir espaços, você poderá usar a sintaxe como esta:
E aqui está a documentação para aplicar e atribuir .
fonte
SettingWithCopyWarning
que faço.df['c'] = df.apply(lambda row: row.a + row.b, axis=1)
Isso é um problema real aqui, ou não devo me preocupar com isso?As respostas acima são perfeitamente válidas, mas existe uma solução vetorizada, na forma de
numpy.select
. Isso permite definir condições e, em seguida, definir saídas para essas condições, com muito mais eficiência do que usarapply
:Primeiro, defina as condições:
Agora, defina as saídas correspondentes:
Finalmente, usando
numpy.select
:Por que deveria
numpy.select
ser usadoapply
? Aqui estão algumas verificações de desempenho:O uso
numpy.select
nos proporciona um desempenho amplamente aprimorado, e a discrepância só aumenta à medida que os dados aumentam.fonte
.apply()
assume uma função como o primeiro parâmetro; passe alabel_race
função da seguinte maneira:Você não precisa criar uma função lambda para passar em uma função.
fonte
tente isso,
O / P:
use em
.loc
vez deapply
.melhora a vetorização.
.loc
funciona de maneira simples, mascara linhas com base na condição, aplica valores às linhas congeladas.para obter mais detalhes, visite .loc docs
Métricas de desempenho:
Resposta Aceita:
Minha resposta proposta:
fonte