Reasignar valores en la columna de pandas con un dict.

Tengo un diccionario que se ve así: di = {1: "A", 2: "B"}

Me gustaría aplicarlo a la columna “col1” de un dataframe similar a:

  col1 col2 0 wa 1 1 2 2 2 NaN 

Llegar:

  col1 col2 0 wa 1 A 2 2 B NaN 

¿Cómo puedo hacer esto mejor? Por alguna razón, los términos de Google relacionados con esto solo me muestran enlaces sobre cómo hacer columnas a partir de dictados y viceversa: – /

Puedes usar .replace . Por ejemplo:

 >>> df = pd.DataFrame({'col2': {0: 'a', 1: 2, 2: np.nan}, 'col1': {0: 'w', 1: 1, 2: 2}}) >>> di = {1: "A", 2: "B"} >>> df col1 col2 0 wa 1 1 2 2 2 NaN >>> df.replace({"col1": di}) col1 col2 0 wa 1 A 2 2 B NaN 

o directamente en la Series , es decir, df["col1"].replace(di, inplace=True) .

map puede ser mucho más rápido que replace

Si su diccionario tiene más de un par de claves, usar el map puede ser mucho más rápido que replace . Hay dos versiones de este enfoque, dependiendo de si su diccionario mapea exhaustivamente todos los valores posibles (y también si desea que las no coincidencias conserven sus valores o se conviertan en NaNs):

Mapeo exhaustivo

En este caso, la forma es muy simple:

 df['col1'].map(di) # note: if the dictionary does not exhaustively map all # entries then non-matched entries are changed to NaNs 

Aunque el map generalmente toma una función como su argumento, alternativamente puede tomar un diccionario o una serie: Documentación para Pandas.series.map

Mapeo no exhaustivo

Si tiene una asignación no exhaustiva y desea conservar las variables existentes para las no coincidencias, puede agregar fillna :

 df['col1'].map(di).fillna(df['col1']) 

como en la respuesta de @jpp aquí: Reemplace los valores en una serie de pandas a través del diccionario de manera eficiente

Puntos de referencia

Usando los siguientes datos con pandas versión 0.23.1:

 di = {1: "A", 2: "B", 3: "C", 4: "D", 5: "E", 6: "F", 7: "G", 8: "H" } df = pd.DataFrame({ 'col1': np.random.choice( range(1,9), 100000 ) }) 

y probando con %timeit , parece que el map es aproximadamente 10 veces más rápido que replace .

Tenga en cuenta que su aceleración con el map variará con sus datos. La mayor aceleración parece ser con grandes diccionarios y reemplazos exhaustivos. Vea la respuesta de @jpp (vinculada anteriormente) para ver puntos de referencia y discusión más extensos.

Hay un poco de ambigüedad en tu pregunta. Hay al menos tres interpretaciones:

  1. Las claves en di refieren a valores de índice.
  2. las claves en di refieren a df['col1'] valores de df['col1']
  3. las claves en di refieren a las ubicaciones del índice (no la pregunta del OP, pero se lanzan por diversión).

A continuación se muestra una solución para cada caso.


Caso 1: Si las claves de di están destinadas a hacer referencia a valores de índice, entonces podría usar el método de update :

 df['col1'].update(pd.Series(di)) 

Por ejemplo,

 import pandas as pd import numpy as np df = pd.DataFrame({'col1':['w', 10, 20], 'col2': ['a', 30, np.nan]}, index=[1,2,0]) # col1 col2 # 1 wa # 2 10 30 # 0 20 NaN di = {0: "A", 2: "B"} # The value at the 0-index is mapped to 'A', the value at the 2-index is mapped to 'B' df['col1'].update(pd.Series(di)) print(df) 

rendimientos

  col1 col2 1 wa 2 B 30 0 A NaN 

He modificado los valores de tu publicación original para que esté más claro qué está haciendo la update . Observe cómo las claves en di están asociadas con los valores de índice. El orden de los valores del índice, es decir, las ubicaciones del índice, no importa.


Caso 2: Si las claves en di refieren a df['col1'] valores de df['col1'] , entonces @DanAllan y @DSM muestran cómo lograr esto con replace :

 import pandas as pd import numpy as np df = pd.DataFrame({'col1':['w', 10, 20], 'col2': ['a', 30, np.nan]}, index=[1,2,0]) print(df) # col1 col2 # 1 wa # 2 10 30 # 0 20 NaN di = {10: "A", 20: "B"} # The values 10 and 20 are replaced by 'A' and 'B' df['col1'].replace(di, inplace=True) print(df) 

rendimientos

  col1 col2 1 wa 2 A 30 0 B NaN 

Observe cómo, en este caso, las claves en di se cambiaron para coincidir con los valores en df['col1'] .


Caso 3: Si las claves en di refieren a ubicaciones de índice, entonces podría usar

 df['col1'].put(di.keys(), di.values()) 

ya que

 df = pd.DataFrame({'col1':['w', 10, 20], 'col2': ['a', 30, np.nan]}, index=[1,2,0]) di = {0: "A", 2: "B"} # The values at the 0 and 2 index locations are replaced by 'A' and 'B' df['col1'].put(di.keys(), di.values()) print(df) 

rendimientos

  col1 col2 1 A a 2 10 30 0 B NaN 

Aquí, las filas primera y tercera se modificaron, porque las claves en di son 0 y 2 , que con la indexación basada en Python 0 se refieren a las ubicaciones primera y tercera.

Agregando a esta pregunta si alguna vez tiene más de una columna para reasignar en un dataframe:

 def remap(data,dict_labels): """ This function take in a dictionnary of labels : dict_labels and replace the values (previously labelencode) into the string. ex: dict_labels = {{'col1':{1:'A',2:'B'}} """ for field,values in dict_labels.items(): print("I am remapping %s"%field) data.replace({field:values},inplace=True) print("DONE") return data 

Espero que pueda serle de utilidad a alguien.

Aclamaciones

DSM tiene la respuesta aceptada, pero la encoding no parece funcionar para todos. Aquí hay uno que funciona con la versión actual de pandas (0.23.4 a partir de 8/2018):

 import pandas as pd df = pd.DataFrame({'col1': [1, 2, 2, 3, 1], 'col2': ['negative', 'positive', 'neutral', 'neutral', 'positive']}) conversion_dict = {'negative': -1, 'neutral': 0, 'positive': 1} df['converted_column'] = df['col2'].replace(conversion_dict) print(df.head()) 

Verás que se ve como:

  col1 col2 converted_column 0 1 negative -1 1 2 positive 1 2 2 neutral 0 3 3 neutral 0 4 1 positive 1 

Los documentos para pandas.DataFrame.replace están aquí .

Un enfoque más nativo de los pandas es aplicar una función de reemplazo como se muestra a continuación:

 def multiple_replace(dict, text): # Create a regular expression from the dictionary keys regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys()))) # For each match, look-up corresponding value in dictionary return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text) 

Una vez que haya definido la función, puede aplicarla a su dataframe.

 di = {1: "A", 2: "B"} df['col1'] = df.apply(lambda row: multiple_replace(di, row['col1']), axis=1) 

O apply :

 df['col1'].apply(lambda x: {1: "A", 2: "B"}.get(x,x)) 

Manifestación:

 >>> df['col1']=df['col1'].apply(lambda x: {1: "A", 2: "B"}.get(x,x)) >>> df col1 col2 0 wa 1 1 2 2 2 NaN >>>