J'ai un dictionnaire qui ressemble à ceci: di = {1: "A", 2: "B"}
Je voudrais l'appliquer à la colonne "col1" d'une trame de données similaire à:
col1 col2
0 w a
1 1 2
2 2 NaN
obtenir:
col1 col2
0 w a
1 A 2
2 B NaN
Comment puis-je faire cela au mieux? Pour une raison quelconque, les termes de recherche sur Google à ce sujet ne me montrent que des liens sur la façon de créer des colonnes à partir de dict et vice-versa: - /
python
dictionary
pandas
remap
TheChymera
la source
la source
col```` is tuple. The error info is
je ne peux pas comparer les types 'ndarray (dtype = object)' et 'tuple'''`'3.6.1 |Anaconda custom (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)]'
map
peut être beaucoup plus rapide quereplace
Si votre dictionnaire comporte plusieurs clés, son utilisation
map
peut être beaucoup plus rapide quereplace
. Il existe deux versions de cette approche, selon que votre dictionnaire mappe de manière exhaustive toutes les valeurs possibles (et également si vous souhaitez que les non-correspondances conservent leurs valeurs ou soient converties en NaN):Cartographie exhaustive
Dans ce cas, le formulaire est très simple:
Bien que
map
plupart du temps utilise une fonction comme argument, elle peut également prendre un dictionnaire ou une série: Documentation for Pandas.series.mapCartographie non exhaustive
Si vous disposez d'un mappage non exhaustif et souhaitez conserver les variables existantes pour les non-correspondances, vous pouvez ajouter
fillna
:comme dans la réponse de @ jpp ici: remplacer efficacement les valeurs d'une série de pandas via le dictionnaire
Repères
Utilisation des données suivantes avec pandas version 0.23.1:
et les tests avec
%timeit
, il semble quemap
soit environ 10 fois plus rapide quereplace
.Notez que votre accélération avec
map
variera avec vos données. La plus grande accélération semble être avec de gros dictionnaires et des remplacements exhaustifs. Voir la réponse @jpp (liée ci-dessus) pour des références et une discussion plus approfondies.la source
df.replace
fonction, bien que bien rangée et utile pour les petits dict, s'est écrasée après avoir fonctionné pendant environ 20 minutes.map
travaille également sur un index où je ne pouvais pas trouver un moyen de le faire avecreplace
Il y a un peu d'ambiguïté dans votre question. Il existe au moins
troisdeux interprétations:di
réfèrent aux valeurs d'indexdi
réfèrent àdf['col1']
valeursdi
réfèrent aux emplacements d'index (pas la question de l'OP, mais jetées pour le plaisir.)Voici une solution pour chaque cas.
Cas 1: Si les clés de
di
sont destinées à faire référence à des valeurs d'index, vous pouvez alors utiliser laupdate
méthode:Par exemple,
les rendements
J'ai modifié les valeurs de votre message d'origine pour que ce soit plus clair
update
. Notez comment les clésdi
sont associées aux valeurs d'index. L'ordre des valeurs d'index - c'est-à-dire les emplacements d' index - n'a pas d'importance.Cas 2: si les clés dans
di
font référence à desdf['col1']
valeurs, alors @DanAllan et @DSM montrent comment y parvenir avecreplace
:les rendements
Notez comment, dans ce cas, les clés
di
ont été modifiées pour correspondre aux valeurs dedf['col1']
.Cas 3: si les clés se
di
réfèrent à des emplacements d'index, vous pouvez utiliserpuisque
les rendements
Ici, les première et troisième lignes ont été modifiées, car les clés dans
di
sont0
et2
qui, avec l'indexation basée sur 0 de Python, font référence aux premier et troisième emplacements.la source
replace
est tout aussi bon, et peut-être un meilleur mot pour ce qui se passe ici.update()
semble un peu maladroit par rapport àreplace()
, mais au moins ça marche.Ajout à cette question si vous avez déjà plusieurs colonnes à remapper dans une trame de données:
J'espère que cela peut être utile à quelqu'un.
À votre santé
la source
DataFrame.replace()
, bien que je ne sache pas quand elle a été ajoutée.DSM a la réponse acceptée, mais le codage ne semble pas fonctionner pour tout le monde. En voici un qui fonctionne avec la version actuelle des pandas (0.23.4 au 8/2018):
Vous verrez que cela ressemble à:
Les documents pour pandas.DataFrame.replace sont ici .
la source
Series.map()
semble plus flexible.Ou faites
apply
:Démo:
la source
di
dict est un dict de listes? Comment pouvez-vous mapper une seule valeur dans la liste?Étant donné que
map
c'est plus rapide que de remplacer (la solution de @ JohnE), vous devez être prudent avec les mappages non exhaustifs où vous avez l'intention de mapper des valeurs spécifiquesNaN
. La méthode appropriée dans ce cas nécessite que vousmask
la série lorsque vous.fillna
, sinon vous annulez le mappageNaN
.la source
Une belle solution complète qui conserve une carte de vos étiquettes de classe:
De cette façon, vous pouvez à tout moment vous référer à l'étiquette de classe d'origine de labels_dict.
la source
Dans le prolongement de ce qui a été proposé par Nico Coallier (appliquer à plusieurs colonnes) et U10-Forward (en utilisant le style de méthodes d'application), et en le résumant en une ligne, je propose:
Le
.transform()
traite chaque colonne comme une série. Contrairement à.apply()
ce qui passe les colonnes agrégées dans un DataFrame.Par conséquent, vous pouvez appliquer la méthode Series
map()
.Enfin, et j'ai découvert ce comportement grâce à U10, vous pouvez utiliser toute la série dans l'expression .get (). À moins que j'aie mal compris son comportement et qu'il traite séquentiellement la série au lieu de le faire avec sagesse.
Les
.get(x,x)
comptes pour les valeurs que vous n'avez pas mentionnées dans votre dictionnaire de mappage qui seraient considérées comme Nan sinon par la.map()
méthodela source
.transform()
traite chaque colonne comme une série. Contrairement à.apply()
ce qui passe les colonnes agrégées dans un DataFrame. J'ai juste essayé, çaapply()
marche bien. Il n'est pas nécessaire d'utiliserloc
non plus, cela semble trop complexe.df[["col1", "col2"]].apply(lambda col: col.map(lambda elem: my_dict.get(elem, elem)))
devrait fonctionner très bien. Les.get(x,x)
comptes pour les valeurs que vous n'avez pas mentionnées dans votre dictionnaire de mappage qui seraient considérées comme Nan sinon par la.map()
méthode que vous pourriez également utiliserfillna()
par la suite.Une approche plus native des pandas consiste à appliquer une fonction de remplacement comme ci-dessous:
Une fois que vous avez défini la fonction, vous pouvez l'appliquer à votre trame de données.
la source