Converti dati categoriali in dataframe panda


103

Ho un dataframe con questo tipo di dati (troppe colonne):

col1        int64
col2        int64
col3        category
col4        category
col5        category

Le colonne sembrano così:

Name: col3, dtype: category
Categories (8, object): [B, C, E, G, H, N, S, W]

Voglio convertire tutto il valore nelle colonne in intero in questo modo:

[1, 2, 3, 4, 5, 6, 7, 8]

Ho risolto questo per una colonna con questo:

dataframe['c'] = pandas.Categorical.from_array(dataframe.col3).codes

Ora ho due colonne nel mio dataframe: vecchia col3e nuova ce devo eliminare le vecchie colonne.

Questa è una cattiva pratica. Funziona ma nel mio dataframe molte colonne e non voglio farlo manualmente.

Come funziona questo pitonico e solo abilmente?

Risposte:


166

In primo luogo, per convertire una colonna categoriale ai suoi codici numerici, si può fare questo più facile con: dataframe['c'].cat.codes.
Inoltre, è possibile selezionare automaticamente tutte le colonne con un certo dtype in un dataframe utilizzando select_dtypes. In questo modo, puoi applicare l'operazione sopra su più colonne selezionate automaticamente.

Prima di fare un esempio di dataframe:

In [75]: df = pd.DataFrame({'col1':[1,2,3,4,5], 'col2':list('abcab'),  'col3':list('ababb')})

In [76]: df['col2'] = df['col2'].astype('category')

In [77]: df['col3'] = df['col3'].astype('category')

In [78]: df.dtypes
Out[78]:
col1       int64
col2    category
col3    category
dtype: object

Quindi utilizzando select_dtypesper selezionare le colonne e quindi applicando .cat.codessu ciascuna di queste colonne, è possibile ottenere il seguente risultato:

In [80]: cat_columns = df.select_dtypes(['category']).columns

In [81]: cat_columns
Out[81]: Index([u'col2', u'col3'], dtype='object')

In [83]: df[cat_columns] = df[cat_columns].apply(lambda x: x.cat.codes)

In [84]: df
Out[84]:
   col1  col2  col3
0     1     0     0
1     2     1     1
2     3     2     0
3     4     0     1
4     5     1     1

14
c'è un modo semplice per ottenere una mappatura tra il codice della categoria e i valori della stringa della categoria?
Allan Ruin

5
Puoi usare: df['col2'].cat.categoriesper esempio.
ogrisel

13
Facendo notare a chiunque sia preoccupato che questo sarà NaN-1
mappato

2
Adoro le 2 battute;)
Jose A

Fai attenzione che se il categoriale è ordinato (un ordinale), i codici numerici restituiti da cat.codespotrebbero NON essere quelli che vedi nella serie!
paulperry

27

Questo funziona per me:

pandas.factorize( ['B', 'C', 'D', 'B'] )[0]

Produzione:

[0, 1, 2, 0]

20

Se la tua preoccupazione era solo quella di creare una colonna in più e di eliminarla in un secondo momento, usa una nuova colonna in primo luogo.

dataframe = pd.DataFrame({'col1':[1,2,3,4,5], 'col2':list('abcab'),  'col3':list('ababb')})
dataframe.col3 = pd.Categorical.from_array(dataframe.col3).codes

Hai fatto. Ora come Categorical.from_arrayè deprecato, usa Categoricaldirettamente

dataframe.col3 = pd.Categorical(dataframe.col3).codes

Se hai anche bisogno della mappatura dall'indice all'etichetta, c'è un modo ancora migliore per lo stesso

dataframe.col3, mapping_index = pd.Series(dataframe.col3).factorize()

controlla sotto

print(dataframe)
print(mapping_index.get_loc("c"))

11

Qui è necessario convertire più colonne. Quindi, un approccio che ho usato è ..

for col_name in df.columns:
    if(df[col_name].dtype == 'object'):
        df[col_name]= df[col_name].astype('category')
        df[col_name] = df[col_name].cat.codes

Questo converte tutte le colonne di tipo stringa / oggetto in categoriale. Quindi applica i codici a ciascun tipo di categoria.


3

Per convertire i dati categoriali nella colonna C dei dati del set di dati , è necessario eseguire le seguenti operazioni:

from sklearn.preprocessing import LabelEncoder 
labelencoder= LabelEncoder() #initializing an object of class LabelEncoder
data['C'] = labelencoder.fit_transform(data['C']) #fitting and transforming the desired categorical column.

2

Quello che faccio è replacevalorizzare.

Come questo-

df['col'].replace(to_replace=['category_1', 'category_2', 'category_3'], value=[1, 2, 3], inplace=True)

In questo modo, se la colcolonna ha valori categoriali, questi vengono sostituiti dai valori numerici.


1

@ Quickbeam2k1, vedi sotto -

dataset=pd.read_csv('Data2.csv')
np.set_printoptions(threshold=np.nan)
X = dataset.iloc[:,:].values

Utilizzando sklearn inserisci qui la descrizione dell'immagine

from sklearn.preprocessing import LabelEncoder
labelencoder_X=LabelEncoder()
X[:,0] = labelencoder_X.fit_transform(X[:,0])

3
Perché non hai appena corretto la tua risposta precedente? Sorprendentemente, stai usando fit_transformora invece di transform_fite corretto la definizione di labelencoder. Perché lo usi iloc[:,:]? questo è inutile. Qual è il motivo dietro l'immagine? Nel caso volessi dimostrare a me e @theGtknerd di aver sbagliato.
Quickbeam2k1

0

Per una certa colonna, se non ti interessa l'ordine, usa questo

df['col1_num'] = df['col1'].apply(lambda x: np.where(df['col1'].unique()==x)[0][0])

Se ti interessa l'ordine, specificali come un elenco e usa questo

df['col1_num'] = df['col1'].apply(lambda x: ['first', 'second', 'third'].index(x))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.