Pandas: convierte categorías en números

82

Supongamos que tengo un marco de datos con países que va como:

cc | temp
US | 37.0
CA | 12.0
US | 35.0
AU | 20.0

Sé que hay una función pd.get_dummies para convertir los países a 'codificaciones one-hot'. Sin embargo, deseo convertirlos en índices en su lugar, de modo que obtengo en su cc_index = [1,2,1,3]lugar.

Supongo que hay una forma más rápida que usar get_dummies junto con una cláusula where numpy como se muestra a continuación:

[np.where(x) for x in df.cc.get_dummies().values]

Esto es algo más fácil de hacer en R usando 'factores', así que espero que los pandas tengan algo similar.

sachinruk
fuente
2
¿Te refieres cc_index = [0,1,0,2]?
juanpa.arrivillaga
1
seguro, me olvidé del índice python 0
sachinruk
Las series categóricas o las columnas en un DataFrame pueden ayudar.
min2bro

Respuestas:

143

Primero, cambie el tipo de columna:

df.cc = pd.Categorical(df.cc)

Ahora los datos se ven similares pero se almacenan categóricamente. Para capturar los códigos de categoría:

df['code'] = df.cc.cat.codes

Ahora tu tienes:

   cc  temp  code
0  US  37.0     2
1  CA  12.0     1
2  US  35.0     2
3  AU  20.0     0

Si no desea modificar su DataFrame sino simplemente obtener los códigos:

df.cc.astype('category').cat.codes

O use la columna categórica como índice:

df2 = pd.DataFrame(df.temp)
df2.index = pd.CategoricalIndex(df.cc)
John Zwinck
fuente
2
La llamada df.cc.cat.codesparece haber cambiado a solo df.cc.codes?
Andreas Storvik Strauman
Tenga en cuenta que si le faltan valores, se codificarán en -1. Si desea evitar tratar este caso, puede convertir primero en una cadena: df.cc.astype ('str'). Astype ('category'). Cat.codes
Guy s
23

Si solo desea transformar su serie en identificadores enteros, puede usar pd.factorize.

Tenga en cuenta que esta solución, a diferencia de pd.Categorical, no se ordenará alfabéticamente. Entonces se asignará el primer país 0. Si desea comenzar desde 1, puede agregar una constante:

df['code'] = pd.factorize(df['cc'])[0] + 1

print(df)

   cc  temp  code
0  US  37.0     1
1  CA  12.0     2
2  US  35.0     1
3  AU  20.0     3

Si desea ordenar alfabéticamente, especifique sort=True:

df['code'] = pd.factorize(df['cc'], sort=True)[0] + 1 
jpp
fuente
11

Si está utilizando la sklearnbiblioteca, puede utilizar LabelEncoder. Por ejemplo pd.Categorical, las cadenas de entrada se ordenan alfabéticamente antes de la codificación.

from sklearn.preprocessing import LabelEncoder

LE = LabelEncoder()
df['code'] = LE.fit_transform(df['cc'])

print(df)

   cc  temp  code
0  US  37.0     2
1  CA  12.0     1
2  US  35.0     2
3  AU  20.0     0
jpp
fuente
2

Pruebe esto, convierta a un número basado en la frecuencia (alta frecuencia - número alto):

labels = df[col].value_counts(ascending=True).index.tolist()
codes = range(1,len(labels)+1)
df[col].replace(labels,codes,inplace=True)
Palepalli Surendra Reddy
fuente
1

Cambiará cualquier columna a Números. No creará una nueva columna, solo reemplazará los valores con datos numéricos.

def characters_to_numb(*args): for arg in args: df[arg] = pd.Categorical(df[arg]) df[arg] = df[arg].cat.codes return df

Denis Kalyan
fuente
0

Código de una línea:

df[['cc']] = df[['cc']].apply(lambda col:pd.Categorical(col).codes)

Esto también funciona si tiene list_of_columns:

df[list_of_columns] = df[list_of_columns].apply(lambda col:pd.Categorical(col).codes)

Además, si desea mantener sus NaNvalores, puede aplicar un reemplazo:

df[['cc']] = df[['cc']].apply(lambda col:pd.Categorical(col).codes).replace(-1,np.nan)
Piotro
fuente