Estoy haciendo esto para hacer números de variables categóricas
>>> df = pd.DataFrame({'x':['good', 'bad', 'good', 'great']}, dtype='category') x 0 good 1 bad 2 good 3 great
¿Cómo puedo obtener la asignación entre los valores originales y los nuevos valores?
Puede crear una asignación de diccionario enumerando (de forma similar a crear un diccionario a partir de una lista creando claves de diccionario a partir de los índices de la lista):
dict( enumerate(df['x'].cat.categories ) ) # {0: 'bad', 1: 'good', 2: 'great'}
Alternativamente, puede asignar los valores y códigos en cada fila:
dict( zip( df['x'].cat.codes, df['x'] ) ) # {0: 'bad', 1: 'good', 2: 'great'}
Es un poco más transparente lo que está sucediendo aquí, y posiblemente más seguro por esa razón. También es mucho menos eficiente ya que la longitud de los argumentos para zip()
es len(df)
mientras que la longitud de df['x'].cat.categories
es solo el conteo de valores únicos y generalmente mucho más corta que len(df)
.
La razón por la que el Método 1 funciona es que las categorías tienen un Tipo de Índice:
type( df['x'].cat.categories ) # pandas.core.indexes.base.Index
y en este caso, busca valores en un índice tal como lo harías con una lista.
Hay un par de maneras de verificar que el Método 1 funciona. Primero, puede verificar que un viaje de ida y vuelta retenga los valores correctos:
(df['x'] == df['x'].cat.codes.map( dict( enumerate(df['x'].cat.categories) ) ).astype('category')).all() # True
o puede verificar que el Método 1 y el Método 2 den la misma respuesta:
(dict( enumerate(df['x'].cat.categories ) ) == dict( zip( df['x'].cat.codes, df['x'] ) )) # True