1
votes

Mappage des valeurs en place (par exemple avec Gender) de string à int dans la trame de données Pandas

J'ai un Dataframe appelé df_base qui ressemble à ceci. Comme vous pouvez le voir, il existe une colonne intitulée Sex qui est masculin ou féminin . Je veux mapper ces valeurs à 0 et 1, respectivement.

+---------+---------+
| Old Sex | New Sex |
+---------+---------+
| male    |       0 |
| female  |       1 |
| female  |       1 |
| female  |       1 |
| male    |       0 |
+---------+---------+

Il y a quelques méthodes que j'ai vues sur StackOverflow mais je me demande quelle est la plus efficace pour effectuer le mappage suivant:

+---+-------------+----------+--------+---------------------------------------------------+--------+-----+-------+-------+------------------+---------+-------+----------+
|   | PassengerId | Survived | Pclass |                       Name                        |  Sex   | Age | SibSp | Parch |      Ticket      |  Fare   | Cabin | Embarked |
+---+-------------+----------+--------+---------------------------------------------------+--------+-----+-------+-------+------------------+---------+-------+----------+
| 0 |           1 |        0 |      3 | Braund, Mr. Owen Harris                           | male   |  22 |     1 |     0 | A/5 21171        |    7.25 | NaN   | S        |
| 1 |           2 |        1 |      1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female |  38 |     1 |     0 | PC 17599         | 71.2833 | C85   | C        |
| 2 |           3 |        1 |      3 | Heikkinen, Miss. Laina                            | female |  26 |     0 |     0 | STON/O2. 3101282 |   7.925 | NaN   | S        |
| 3 |           4 |        1 |      1 | Futrelle, Mrs. Jacques Heath (Lily May Peel)      | female |  35 |     1 |     0 | 113803           |    53.1 | C123  | S        |
| 4 |           5 |        0 |      3 | Allen, Mr. William Henry                          | male   |  35 |     0 |     0 | 373450           |    8.05 | NaN   | S        |
+---+-------------+----------+--------+---------------------------------------------------+--------+-----+-------+-------+------------------+---------+-------+----------+

J'utilise ceci:

df_base ['Sex']. replace (['male', 'female '], [0,1], inplace = True)

... mais je ne peux pas m'empêcher de penser que c'est un peu de mauvaise qualité. Existe-t-il une meilleure façon de le faire? Il y a aussi l'utilisation de .loc mais qui boucle autour des lignes du Dataframe, est donc moins efficace, non?


6 commentaires

Pourquoi ne vois-je pas de personnes suggérant des doublons alors que la question est en fait un double?


@coldspeed, je n'ai jamais entendu parler de ce fil. Donc, je ne pouvais pas le diffuser en tant que dups.


@pygo Je n'ai rien contre les gens qui suggèrent des dupes, mais je n'aime pas les doubles standards. Je le vois partout, et plus pour certains utilisateurs que pour d'autres.


@coldspeed - Oui, la solution standard est replace / map, mais si OP a besoin de performances, il existe également une autre solution, donc pas de fermeture par dupe de ma part.


@jezrael Chaque question peut être laissée ouverte avec ce raisonnement. Je suis sûr que vous avez déjà utilisé le même raisonnement pour répondre à des questions similaires, alors trouvez-en une et marquez-la comme dupe. Ou ajoutez une réponse à la cible de dupe. Vous obtiendrez ainsi beaucoup plus de représentants que de répondre à des questions comme celle-ci encore et encore.


@coldspeed - oui, mais voici seulement 2 valeurs dans la colonne Sex , donc ce n'est qu'un cas spécial, donc pas possible d'ajouter une réponse à dupe - c'est une bonne solution générale pour remplacer de nombreuses valeurs ... Parce que seulement 2 valeurs de remplacement est une solution plus rapide possible.


3 Réponses :


4
votes

Je pense que voici une utilisation meilleure / plus rapide carte par dictionnaire si seuls homme et femme existent dans la colonne Sex :

perfplot.show(
    setup=make_df,
    kernels=[ma,  rep1, nwhere, mask1, mask2],
    n_range=[2**k for k in range(2, 18)],
    logx=True,
    logy=True,
    equality_check=False,  # rows may appear in different order
    xlabel='len(df)')


0 commentaires

1
votes

Une autre solution que vous pouvez utiliser avec np.where :

Juste un exemple de DataFrame:

>>> df['new_Sex'] = np.where(df['Sex'] != 'male', 1, 0)
>>> df
      Sex  new_Sex
0    male        0
1  female        1
2  female        1
3  female        1
4    male        0

Sur la base de la condition, créez une nouvelle colonne new_Sex

>>> df['new_Sex'] = np.where(df['Sex'] == 'male', 0, 1)
>>> df
      Sex  new_Sex
0    male        0
1  female        1
2  female        1
3  female        1
4    male        0

OR:

>>> df
      Sex
0    male
1  female
2  female
3  female
4    male


0 commentaires

2
votes

Mon instinct aurait suggéré d'utiliser .map () , mais j'ai fait une comparaison entre votre solution et la carte, basée sur une base de données avec 1500 valeurs masculines / féminines aléatoires.

%timeit df_base['Sex_new'] = (df_base['Sex'] == 'female').astype(int)
1000 loops, best of 3: 388 µs per loop

Modifié Basé sur le commentaire de Coldspeeds, et parce que le réaffecter est une meilleure comparaison avec les autres:

%timeit df_base['Sex_new'] = np.where(df_base['Sex'] == 'male', 0, 1)
1000 loops, best of 3: 331 µs per loop

Donc en fait plus lent .map () ...!

Donc, sur la base de cet exemple, votre solution 'de mauvaise qualité' semble plus rapide que .map () ...

Edit[

La solution de pygo:

%timeit df_base['Sex_new'] = df_base['Sex'].replace(['male','female'],[0,1])
1000 loops, best of 3: 968 µs per loop

Tellement plus vite! p >

La solution de Jezrael avec .astype(int):

%timeit df_base['Sex_new'] = df_base['Sex'].map({'male': 0,'female': 1})
1000 loops, best of 3: 653 µs per loop

Donc aussi plus rapide que .map () et .replace () .


12 commentaires

Qu'en est-il de la comparaison de df ['Old_Sex'] = np.where (df ['Sex'] == 'male', 0, 1) ?


Et vérifiez ceci pour map / replace comparaison


Oui, la solution avec numpy sera plus rapide.


Ou df_base ['Sex'] = (df_base ['Sex']. Values ​​== 'female'). Astype (int)


Notez que df_base ['Sex']. Replace (['male', 'female'], [0,1], inplace = True) ne fonctionnera pas car inplace = True on Series with replace a toujours été problématique. Attribuez-le à nouveau.


Merci pour les timings, mais j'obtiens autre chose, replace est plus lent pour moi, vérifiez ma réponse. Quel est votre code pour tester les performances?


@jezrael: C'est aussi pour moi si je le réaffecte. Voir la modification (je l'ai déjà publiée en bas, mais je l'ai rendue plus visible maintenant). J'aime vraiment votre intrigue des différentes options!


@NielsHenkens - Oui, je l'aime aussi, je l'apprends de unutbu :)


J'ai popularisé perfplot dans cette réponse que j'ai écrite récemment


@jezrael ces intrigues de perf sont très belles, je vais essayer de l'apprendre :-)


@coldspeed, le post est vraiment sympa, mais quelle méthode utilisez-vous pour tracer les graphiques perfplot?


@pygo oui, faites défiler vers le bas de l'article, j'y ai ajouté tous les extraits de code.