valores valor sumar recorrer funcion dict diccionarios diccionario consultar buscar actualizar python dictionary pandas remap

python - sumar - Reasignación de valores en la columna de pandas con un dict



recorrer un diccionario en python (5)

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

Me gustaría aplicarlo a la columna "col1" de un marco de datos similar a:

col1 col2 0 w a 1 1 2 2 2 NaN

Llegar:

col1 col2 0 w a 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 dicts y viceversa: - /


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 ser útil para alguien.

Aclamaciones


Esta es una respuesta alternativa que puede ser mucho más rápida cuando su diccionario tiene más de un par de claves. Si su diccionario mapea exhaustivamente todos los valores posibles, esto toma una forma 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 toma más comúnmente una función como argumento, alternativamente puede tomar un diccionario o una serie: Documentación para Pandas.series.map

Sin un mapeo exhaustivo, debe agregar la update si desea evitar que las no concordancias se cambien a NaN.

df[''col1''].update( df[''col1''].map(di) ) # note: series update is an inplace operation

Aquí hay algunos tiempos para el caso exhaustivo en un marco de datos con 100.000 filas y 8 teclas de diccionario (es aproximadamente 10 veces más rápido).

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 ) }) %timeit df.replace({"col1": di}) 10 loops, best of 3: 55.6 ms per loop %timeit df[''col1''].map(di) 100 loops, best of 3: 4.16 ms per loop


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 teclas en di referencia a df[''col1''] valores df[''col1'']
  3. las claves en di refieren a las ubicaciones de los índices (no la pregunta del OP, sino que se envían por diversión).

A continuación hay una solución para cada caso.

Caso 1: Si las claves de di están destinadas a referirse 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 w a # 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 w a 2 B 30 0 A NaN

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

Caso 2: Si las claves en di referencia a df[''col1''] valores 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 w a # 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 w a 2 A 30 0 B NaN

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

Caso 3: si las claves en di refieren a ubicaciones de índice, entonces podrías 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í, la primera y la tercera filas fueron alteradas, porque las claves en di son 0 y 2 , que con la indexación basada en 0 de Python se refieren a la primera y tercera ubicación.


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 w a 1 1 2 2 2 NaN >>> df.replace({"col1": di}) col1 col2 0 w a 1 A 2 2 B NaN

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


Un enfoque más pandas nativos es aplicar una función de reemplazo de la siguiente manera:

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 marco de datos.

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