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 is
no 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)]'
map
puede ser mucho más rápido quereplace
Si su diccionario tiene más de un par de claves, el uso
map
puede 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
map
má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 quemap
es aproximadamente 10 veces más rápido quereplace
.Tenga en cuenta que su aceleración
map
variará 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.replace
función, aunque ordenada y útil para pequeños dictados, se bloqueó después de ejecutarse durante aproximadamente 20 minutos.map
también funciona en un índice en el que no pude encontrar una manera de hacerloreplace
Hay un poco de ambigüedad en su pregunta. Hay al menos
tresinterpretaciones:di
refieren a valores de índicedi
refieren adf['col1']
valoresdi
refieren 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
di
están destinadas a hacer referencia a valores de índice, entonces podría usar elupdate
método:Por ejemplo,
rendimientos
He modificado los valores de tu publicación original para que quede más claro lo que
update
está haciendo. Observe cómo las clavesdi
se 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
di
refieren adf['col1']
valores, entonces @DanAllan y @DSM muestran cómo lograr esto conreplace
:rendimientos
Tenga en cuenta cómo, en este caso,
di
se modificaron las claves para que coincidan con los valores dedf['col1']
.Caso 3: si las claves se
di
refieren a ubicaciones de índice, entonces podría usarya que
rendimientos
Aquí, la primera y la tercera fila fueron alteradas, porque las claves en
di
son0
y2
, que con la indexación basada en 0 de Python se refieren a las ubicaciones primera y tercera.fuente
replace
es 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
di
dict es un dict de listas? ¿Cómo puede asignar solo un valor en la lista?Dado que
map
es 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 seamask
la 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 usarloc
tampoco, 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