Obtener mapeo de variables categóricas en pandas

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?

Método 1

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'} 

Método 2

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) .

Discusión adicional

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