Remplacement des valeurs de colonne dans un DataFrame Pandas

141

J'essaye de remplacer les valeurs dans une colonne d'un dataframe. La colonne («femme») contient uniquement les valeurs «femme» et «homme».

J'ai essayé ce qui suit:

w['female']['female']='1'
w['female']['male']='0' 

Mais recevez exactement la même copie des résultats précédents.

Je voudrais idéalement obtenir une sortie qui ressemble à la boucle suivante par élément.

if w['female'] =='female':
    w['female'] = '1';
else:
    w['female'] = '0';

J'ai parcouru la documentation de gotchas ( http://pandas.pydata.org/pandas-docs/stable/gotchas.html ) mais n'arrive pas à comprendre pourquoi rien ne se passe.

Toute aide serait appréciée.

Noir
la source

Réponses:

259

Si je comprends bien, vous voulez quelque chose comme ceci:

w['female'] = w['female'].map({'female': 1, 'male': 0})

(Ici, je convertis les valeurs en nombres au lieu de chaînes contenant des nombres. Vous pouvez les convertir en "1"et "0", si vous le souhaitez vraiment, mais je ne sais pas pourquoi vous le souhaitez.)

La raison pour laquelle votre code ne fonctionne pas est que l'utilisation ['female']sur une colonne (la deuxième 'female'de votre w['female']['female']) ne signifie pas "sélectionner les lignes dont la valeur est" femme "". Cela signifie sélectionner des lignes où l' index est «femelle», dont il peut ne pas y en avoir dans votre DataFrame.

BrenBarn
la source
6
Merci. Exactement ce que je cherchais. Si je devais mapper «femelle» à 1 et toute autre chose à «0». Comment cela fonctionnerait-il?
Noir
17
utilisez ceci uniquement, si toutes les valeurs de la colonne sont données dans la fonction de carte. Les valeurs de colonne non spécifiées dans la fonction de carte seront remplacées par nan.
Chandra
1
Je recommanderais également d'utiliser la .locsyntaxe pour éviter SettingWithCopyWarning: pandas.pydata.org/pandas-docs/stable/…
NickBraunagel
2
au lieu de .map j'ai utilisé .replace
JS noob
Comment puis-je me débarrasser du "." des milliers sur deux colonnes ou plus, ne peut pas comprendre. merci beaucoup
M. Mariscal
115

Vous pouvez modifier un sous-ensemble d'un dataframe à l'aide de loc:

df.loc[<row selection>, <column selection>]

Dans ce cas:

w.loc[w.female != 'female', 'female'] = 0
w.loc[w.female == 'female', 'female'] = 1
Jimmy Petersson
la source
1
Comment l'adapterais-je pour ne pas avoir besoin de sélectionner des lignes spécifiques via une condition, juste toutes les lignes d'une colonne particulière? Modifiez donc toutes les cellules d'une colonne en une valeur particulière.
Dhruv Ghulati
3
@DhruvGhulati, vous utiliseriez df.loc [:, <sélection de colonne>]
40
w.female.replace(to_replace=dict(female=1, male=0), inplace=True)

Voir la documentation pandas.DataFrame.replace () .

jfs
la source
C'est la meilleure solution pour le problème que j'ai, merci!
Andrew Brēza le
38

Légère variation:

w.female.replace(['male', 'female'], [1, 0], inplace=True)
Deckard
la source
19

Cela devrait également fonctionner:

w.female[w.female == 'female'] = 1 
w.female[w.female == 'male']   = 0
Nick Crawford
la source
11

Vous pouvez également utiliser applyavec .getie

w['female'] = w['female'].apply({'male':0, 'female':1}.get):

w = pd.DataFrame({'female':['female','male','female']})
print(w)

Dataframe w:

   female
0  female
1    male
2  female

Utilisation applypour remplacer les valeurs du dictionnaire:

w['female'] = w['female'].apply({'male':0, 'female':1}.get)
print(w)

Résultat:

   female
0       1
1       0
2       1 

Remarque: apply avec le dictionnaire doit être utilisé si toutes les valeurs possibles des colonnes dans le dataframe sont définies dans le dictionnaire sinon, il sera vide pour celles non définies dans le dictionnaire.

étudiant
la source
8

C'est très compact:

w['female'][w['female'] == 'female']=1
w['female'][w['female'] == 'male']=0

Un autre bon:

w['female'] = w['female'].replace(regex='female', value=1)
w['female'] = w['female'].replace(regex='male', value=0)
Azz
la source
Le premier exemple est l'indexation chaînée et est mis en garde car il ne peut pas garantir si le df résultant est une copie ou une vue. Voir l' indexation chaînée
Nordle
7

Il existe également la fonction intégrée pd.get_dummies pour ces types d'affectations:

w['female'] = pd.get_dummies(w['female'],drop_first = True)

Cela vous donne un bloc de données avec deux colonnes, une pour chaque valeur qui apparaît dans w ['female'], dont vous supprimez la première (car vous pouvez la déduire de celle qui reste). La nouvelle colonne est automatiquement nommée comme la chaîne que vous avez remplacée.

Ceci est particulièrement utile si vous avez des variables catégorielles avec plus de deux valeurs possibles. Cette fonction crée autant de variables fictives nécessaires pour distinguer tous les cas. Faites attention alors à ne pas affecter la totalité du bloc de données à une seule colonne, mais à la place, si w ['female'] peut être 'male', 'female' ou 'neutral', faites quelque chose comme ceci:

w = pd.concat([w, pd.get_dummies(w['female'], drop_first = True)], axis = 1])
w.drop('female', axis = 1, inplace = True)

Ensuite, vous vous retrouvez avec deux nouvelles colonnes vous donnant le codage factice de «femelle» et vous vous débarrassez de la colonne avec les chaînes.

Galliwuzz
la source
4

Utilisation Series.mapavecSeries.fillna

Si votre colonne contient plus de chaînes que seulement femaleet male, Series.mapéchouera dans ce cas car elle retourneraNaN pour d'autres valeurs.

C'est pourquoi nous devons l'enchaîner avec fillna:

Exemple pourquoi .mapéchoue :

df = pd.DataFrame({'female':['male', 'female', 'female', 'male', 'other', 'other']})

   female
0    male
1  female
2  female
3    male
4   other
5   other
df['female'].map({'female': '1', 'male': '0'})

0      0
1      1
2      1
3      0
4    NaN
5    NaN
Name: female, dtype: object

Pour la bonne méthode, nous enchaînons mapavec fillna, donc nous remplissons le NaNavec les valeurs de la colonne d'origine:

df['female'].map({'female': '1', 'male': '0'}).fillna(df['female'])

0        0
1        1
2        1
3        0
4    other
5    other
Name: female, dtype: object
Erfan
la source
2

Il existe également une fonction dans pandasappelée factorizeque vous pouvez utiliser pour effectuer automatiquement ce type de travail. Il convertit les étiquettes aux numéros: ['male', 'female', 'male'] -> [0, 1, 0]. Voir cette réponse pour plus d'informations.

Roald
la source
0

Je pense qu'en réponse, il faut indiquer quel type d'objet obtenez-vous dans toutes les méthodes suggérées ci-dessus: s'agit-il d'une série ou d'un DataFrame.

Lorsque vous obtenez une colonne par w.female.ou w[[2]](où, supposons, 2 est le numéro de votre colonne), vous récupérez DataFrame. Donc, dans ce cas, vous pouvez utiliser des méthodes DataFrame comme .replace.

Lorsque vous utilisez .locou que ilocvous récupérez Series, et Series n'ont pas de .replaceméthode, vous devez donc utiliser des méthodes comme apply, mapet ainsi de suite.

Alex-droïde AD
la source