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 dictados y viceversa: - /
python
dictionary
pandas
remap
TheChymera
fuente
fuente

col```` is tuple. The error info isno puedo comparar los tipos 'ndarray (dtype = object)' y 'tuple' '' ''3.6.1 |Anaconda custom (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)]'mappuede ser mucho más rápido quereplaceSi su diccionario tiene más de un par de claves, el uso
mappuede ser mucho más rápido quereplace. 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 NaN):Mapeo exhaustivo
En este caso, el formulario es muy simple:
Aunque
mapmás comúnmente toma una función como argumento, también puede tomar un diccionario o una serie: Documentación para Pandas.series.mapMapeo no exhaustivo
Si tiene un mapeo no exhaustivo y desea retener las variables existentes para no coincidencias, puede agregar
fillna:como en la respuesta de @ jpp aquí: Reemplazar 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:
y probando con
%timeit, parece quemapes aproximadamente 10 veces más rápido quereplace.Tenga en cuenta que su aceleración
mapvariará con sus datos. La mayor aceleración parece ser con grandes diccionarios y reemplazos exhaustivos. Consulte la respuesta @jpp (vinculada anteriormente) para obtener puntos de referencia y debates más extensos.fuente
df.replacefunción, aunque ordenada y útil para pequeños dictados, se bloqueó después de ejecutarse durante aproximadamente 20 minutos.maptambién funciona en un índice en el que no pude encontrar una manera de hacerloreplaceHay un poco de ambigüedad en su pregunta. Hay al menos
tresinterpretaciones:direfieren a valores de índicedirefieren adf['col1']valoresdirefieren a ubicaciones de índice (no es la pregunta del OP, pero son divertidas).A continuación hay una solución para cada caso.
Caso 1: Si las claves de
diestán destinadas a hacer referencia a valores de índice, entonces podría usar elupdatemétodo:Por ejemplo,
rendimientos
He modificado los valores de tu publicación original para que quede más claro lo que
updateestá haciendo. Observe cómo las clavesdise asocian con valores de índice. El orden de los valores del índice, es decir, las ubicaciones del índice , no importa.Caso 2: Si las claves se
direfieren adf['col1']valores, entonces @DanAllan y @DSM muestran cómo lograr esto conreplace:rendimientos
Tenga en cuenta cómo, en este caso,
dise modificaron las claves para que coincidan con los valores dedf['col1'].Caso 3: si las claves se
direfieren a ubicaciones de índice, entonces podría usarya que
rendimientos
Aquí, la primera y la tercera fila fueron alteradas, porque las claves en
dison0y2, que con la indexación basada en 0 de Python se refieren a las ubicaciones primera y tercera.fuente
replacees igualmente bueno, y tal vez una mejor palabra para lo que está sucediendo aquí.update()parece un poco torpe en comparación conreplace(), pero al menos funciona.Agregando a esta pregunta si alguna vez tiene más de una columna para reasignar en un marco de datos:
Espero que pueda ser útil para alguien.
Salud
fuente
DataFrame.replace(), aunque no sé cuándo se agregó.DSM tiene la respuesta aceptada, pero la codificación 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):
Verás que se ve así:
Los documentos para pandas.DataFrame.replace están aquí .
fuente
Series.map()parece más flexible.O hacer
apply:Manifestación:
fuente
didict es un dict de listas? ¿Cómo puede asignar solo un valor en la lista?Dado que
mapes más rápido que reemplazar (solución de @ JohnE), debe tener cuidado con las asignaciones no exhaustivas en las que pretende asignar valores específicosNaN. El método adecuado en este caso requiere que usted seamaskla Serie cuando usted.fillna, de lo contrario, deshaga la asignaciónNaN.fuente
Una buena solución completa que mantiene un mapa de las etiquetas de su clase:
De esta manera, puede referirse en cualquier momento a la etiqueta de clase original de labels_dict.
fuente
Como una extensión de lo que ha propuesto Nico Coallier (se aplica a varias columnas) y U10-Forward (utilizando el estilo de aplicación de métodos), y resumiendo en una línea, propongo:
El
.transform()procesa cada columna como una serie. Al contrario de lo.apply()que pasa las columnas agregadas en un DataFrame.En consecuencia, puede aplicar el método de la serie
map().Finalmente, y descubrí este comportamiento gracias a U10, puedes usar toda la serie en la expresión .get (). A menos que haya malinterpretado su comportamiento y procese secuencialmente la serie en lugar de ser torpe.
Las
.get(x,x)cuentas de los valores que no mencionó en su diccionario de mapeo que de otra manera se considerarían como Nan por el.map()métodofuente
.transform()procesa cada columna como una serie. Al contrario de lo.apply()que pasa las columnas agregadas en un DataFrame. Acabo de intentarlo,apply()funciona bien. No hay necesidad de usarloctampoco, esto parece demasiado complejo.df[["col1", "col2"]].apply(lambda col: col.map(lambda elem: my_dict.get(elem, elem)))debería funcionar bien. Las.get(x,x)cuentas de los valores que no mencionó en su diccionario de mapeo que, de lo contrario, se considerarían Nan por el.map()método que también podría usarfillna()después.Un enfoque de pandas más nativo es aplicar una función de reemplazo como se muestra a continuación:
Una vez que haya definido la función, puede aplicarla a su marco de datos.
fuente