Konversikan data kategorikal dalam pandas dataframe

103

Saya memiliki kerangka data dengan jenis data ini (terlalu banyak kolom):

col1        int64
col2        int64
col3        category
col4        category
col5        category

Kolom terlihat seperti ini:

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

Saya ingin mengubah semua nilai dalam kolom menjadi integer seperti ini:

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

Saya menyelesaikan ini untuk satu kolom dengan ini:

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

Sekarang saya memiliki dua kolom di dataframe saya - lama col3dan baru cdan perlu membuang kolom lama.

Itu praktik yang buruk. Ini berfungsi tetapi dalam banyak kolom bingkai data saya dan saya tidak ingin melakukannya secara manual.

Bagaimana pythonic ini dan hanya cerdik?

Gilaztdinov Rustam
sumber

Jawaban:

166

Pertama, untuk mengkonversi kolom kategoris untuk kode numerik, Anda dapat melakukan ini lebih mudah dengan: dataframe['c'].cat.codes.
Selanjutnya, dimungkinkan untuk memilih secara otomatis semua kolom dengan tipe d tertentu dalam kerangka data menggunakan select_dtypes. Dengan cara ini, Anda dapat menerapkan operasi di atas pada beberapa kolom dan dipilih secara otomatis.

Pertama membuat contoh 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

Lalu dengan menggunakan select_dtypesuntuk memilih kolom, lalu menerapkan .cat.codespada setiap kolom ini, Anda bisa mendapatkan hasil sebagai berikut:

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
joris
sumber
14
adakah cara mudah kita mendapatkan pemetaan antara kode kategori dan nilai string kategori?
Allan Ruin
5
Anda dapat menggunakan: df['col2'].cat.categoriesmisalnya.
ogrisel
13
Menunjukkan kepada siapa pun yang khawatir bahwa ini akan memetakan NaNsecara unik ke-1
quietContest
2
Love the 2 liners;)
Jose A
Hati-hati bahwa jika kategorikal diurutkan (sebuah ordinal) maka kode numerik yang dikembalikan oleh cat.codesmungkin BUKAN seperti yang Anda lihat di Seri!
paulperry
27

Ini bekerja untuk saya:

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

Keluaran:

[0, 1, 2, 0]
scottlittle
sumber
20

Jika kekhawatiran Anda hanya membuat kolom tambahan dan menghapusnya nanti, jangan gunakan kolom baru di tempat pertama.

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

Kamu selesai. Sekarang karena Categorical.from_arraysudah usang, gunakan Categoricalsecara langsung

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

Jika Anda juga membutuhkan pemetaan kembali dari indeks ke label, ada cara yang lebih baik untuk hal yang sama

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

periksa di bawah

print(dataframe)
print(mapping_index.get_loc("c"))
Abhishek
sumber
11

Di sini beberapa kolom perlu diubah. Jadi, satu pendekatan yang saya gunakan adalah ..

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

Ini mengubah semua kolom tipe string / objek menjadi kategorikal. Kemudian terapkan kode untuk setiap jenis kategori.

shantanu pathak
sumber
3

Untuk mengonversi data kategorikal di kolom C dari data set data , kita perlu melakukan hal berikut:

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.
Fatemeh Asgarinejad
sumber
2

Apa yang saya lakukan adalah, saya replacemenghargai.

Seperti ini-

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

Dengan cara ini, jika colkolom memiliki nilai kategorik, nilai tersebut diganti dengan nilai numerik.

kebenaran
sumber
1

@ Quickbeam2k1, lihat di bawah -

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

Menggunakan sklearn masukkan deskripsi gambar di sini

from sklearn.preprocessing import LabelEncoder
labelencoder_X=LabelEncoder()
X[:,0] = labelencoder_X.fit_transform(X[:,0])
Prohadoopian
sumber
3
Mengapa Anda tidak mengoreksi jawaban Anda sebelumnya? Anehnya, Anda menggunakan fit_transformsekarang, bukan transform_fitdan mengoreksi definisi labelencoder. Mengapa Anda menggunakan iloc[:,:]? ini tidak berguna. Apa alasan dibalik gambar tersebut? Jika Anda ingin membuktikan kepada saya dan @theGtknerd salah Anda gagal.
Quickbeam2k1
0

Untuk kolom tertentu, jika Anda tidak peduli dengan urutannya, gunakan ini

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

Jika Anda peduli tentang pemesanan, tentukan sebagai daftar dan gunakan ini

df['col1_num'] = df['col1'].apply(lambda x: ['first', 'second', 'third'].index(x))
SaTa
sumber