Je veux appliquer ma fonction personnalisée (il utilise un if-else échelle) à ces six colonnes ( ERI_Hispanic
, ERI_AmerInd_AKNatv
, ERI_Asian
, ERI_Black_Afr.Amer
, ERI_HI_PacIsl
, ERI_White
) dans chaque rangée de mon dataframe.
J'ai essayé différentes méthodes à partir d'autres questions, mais je n'arrive toujours pas à trouver la bonne réponse à mon problème. L'élément critique est que si la personne est considérée comme hispanique, elle ne peut pas être considérée comme autre chose. Même s'ils ont un «1» dans une autre colonne ethnique, ils sont toujours considérés comme hispaniques et non comme deux races ou plus. De même, si la somme de toutes les colonnes ERI est supérieure à 1, elles sont comptées comme deux races ou plus et ne peuvent pas être comptées comme une ethnie unique (sauf pour les Hispaniques). J'espère que cela a du sens. Toute aide sera fortement appréciée.
C'est presque comme faire une boucle for à travers chaque ligne et si chaque enregistrement répond à un critère, ils sont ajoutés à une liste et éliminés de l'original.
À partir de la trame de données ci-dessous, je dois calculer une nouvelle colonne en fonction des spécifications suivantes dans SQL:
========================= CRITÈRES ========================= =======
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”
Commentaire: Si le drapeau ERI pour Hispanique est Vrai (1), l'employé est classé comme «Hispanique»
Commentaire: Si plus d'un drapeau ERI non hispanique est vrai, retournez «Deux ou plus»
====================== 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
Réponses:
OK, deux étapes pour cela - la première consiste à écrire une fonction qui fait la traduction que vous voulez - j'ai mis un exemple en fonction de votre pseudo-code:
Vous voudrez peut-être passer en revue cela, mais cela semble faire l'affaire - notez que le paramètre entrant dans la fonction est considéré comme un objet Series étiqueté "ligne".
Ensuite, utilisez la fonction apply dans pandas pour appliquer la fonction - par exemple
Notez le spécificateur axis = 1, ce qui signifie que l'application se fait au niveau d'une ligne plutôt qu'au niveau d'une colonne. Les résultats sont ici:
Si vous êtes satisfait de ces résultats, exécutez-le à nouveau, en enregistrant les résultats dans une nouvelle colonne dans votre trame de données d'origine.
La trame de données résultante ressemble à ceci (faites défiler vers la droite pour voir la nouvelle colonne):
la source
df.apply(label_race, axis=1)
return 'Other'
ligne àreturn row['rno_defined']
laquelle devrait remplacez la valeur de cette colonne dans les cas où l'ensemble d'instructions if / then ne trouve pas de correspondance (c'est-à-dire où actuellement, vous voyez «Autre»).df.apply(lambda row: label_race (row),axis=1)
todf.apply(label_race, axis=1)
Puisqu'il s'agit du premier résultat Google pour «pandas new column from others», voici un exemple simple:
Si vous obtenez le,
SettingWithCopyWarning
vous pouvez également le faire de cette façon:Source: https://stackoverflow.com/a/12555510/243392
Et si le nom de votre colonne comprend des espaces, vous pouvez utiliser une syntaxe comme celle-ci:
Et voici la documentation pour appliquer et attribuer .
la source
SettingWithCopyWarning
quand je le faisdf['c'] = df.apply(lambda row: row.a + row.b, axis=1)
Est-ce un vrai problème ici, ou ne devrais-je pas m'en inquiéter?Les réponses ci-dessus sont parfaitement valables, mais une solution vectorisée existe, sous la forme de
numpy.select
. Cela vous permet de définir des conditions, puis de définir des sorties pour ces conditions, beaucoup plus efficacement qu'en utilisantapply
:Définissez d'abord les conditions:
Maintenant, définissez les sorties correspondantes:
Enfin, en utilisant
numpy.select
:Pourquoi devrait
numpy.select
être utilisé plusapply
? Voici quelques vérifications de performances:L'utilisation
numpy.select
nous donne des performances considérablement améliorées, et l'écart ne fera qu'augmenter à mesure que les données augmentent.la source
.apply()
prend une fonction comme premier paramètre; passez lalabel_race
fonction comme suit:Vous n'avez pas besoin de créer une fonction lambda pour transmettre une fonction.
la source
essaye ça,
O / P:
utiliser
.loc
au lieu deapply
.il améliore la vectorisation.
.loc
fonctionne de manière simple, masque les lignes en fonction de la condition, applique des valeurs aux lignes figées.pour plus de détails visitez, .loc docs
Indicateurs de performance:
Réponse acceptée:
Ma réponse proposée:
la source