Chuyển đổi hàng loạt cột phân loại trong Pandas (không mã hóa một lần nóng)


12

Tôi có khung dữ liệu gấu trúc với hàng tấn cột phân loại, mà tôi đang dự định sử dụng trong cây quyết định với scikit-learn. Tôi cần chuyển đổi chúng thành các giá trị số (không phải là một vectơ nóng). Tôi có thể làm điều đó với LabelEncoder từ scikit-learn. Vấn đề là có quá nhiều người trong số họ và tôi không muốn chuyển đổi chúng theo cách thủ công.

Điều gì sẽ là một cách dễ dàng để tự động hóa quá trình này.


Hàm get_dummies trong gấu trúc có thể giúp bạn. Kiểm tra tài liệu ở đây để biết thêm chi tiết . Tôi nghĩ rằng nó hoàn toàn bao gồm trường hợp sử dụng này và bạn có thể điều chỉnh thêm hành vi bằng cách cung cấp tiền tố tùy chỉnh.
hssay

Câu trả lời:


11

Nếu các cột phân loại của bạn hiện là ký tự / đối tượng, bạn có thể sử dụng một cái gì đó như thế này để làm từng cái:

char_cols = df.dtypes.pipe(lambda x: x[x == 'object']).index

for c in char_cols:
    df[c] = pd.factorize(df[c])[0]

Nếu bạn cần có thể quay lại các danh mục tôi sẽ tạo một từ điển để lưu mã hóa; cái gì đó như:

char_cols = df.dtypes.pipe(lambda x: x[x == 'object']).index
label_mapping = {}

for c in char_cols:
    df[c], label_mapping[c] = pd.factorize(df[c])

Sử dụng mcien của Julien sẽ xuất ra:

In [3]: print(df)
Out[3]: 
    a   b   c   d
0   0   0   0   0.155463
1   1   1   1   0.496427
2   0   0   2   0.168625
3   2   0   1   0.209681
4   0   2   1   0.661857

In [4]: print(label_mapping)
Out[4]:
{'a': Index(['Var2', 'Var3', 'Var1'], dtype='object'),
 'b': Index(['Var2', 'Var1', 'Var3'], dtype='object'),
 'c': Index(['Var3', 'Var2', 'Var1'], dtype='object')}

Mã của bạn để tìm các objectcột là v hữu ích.
javadba

6

Đầu tiên, hãy tạo một mcve để chơi với:

import pandas as pd
import numpy as np

In [1]: categorical_array = np.random.choice(['Var1','Var2','Var3'],
                                             size=(5,3), p=[0.25,0.5,0.25])
        df = pd.DataFrame(categorical_array,
               columns=map(lambda x:chr(97+x), range(categorical_array.shape[1])))
        # Add another column that isn't categorical but float
        df['d'] = np.random.rand(len(df))
        print(df)

Out[1]:
      a     b     c         d
0  Var3  Var3  Var3  0.953153
1  Var1  Var2  Var1  0.924896
2  Var2  Var2  Var2  0.273205
3  Var2  Var1  Var3  0.459676
4  Var2  Var1  Var1  0.114358

Bây giờ chúng ta có thể sử dụng pd.get_dummies để mã hóa ba cột đầu tiên.

Lưu ý rằng tôi đang sử dụng drop_firsttham số vì các hình N-1nộm là đủ để mô tả đầy đủ các Nkhả năng (ví dụ: nếu a_Var2và bằng a_Var30, thì đó là a_Var1). Ngoài ra, tôi đặc biệt chỉ định các cột nhưng tôi không phải vì nó sẽ là các cột có dtype objecthoặc categorical(nhiều hơn bên dưới).

In [2]: df_encoded = pd.get_dummies(df, columns=['a','b', 'c'], drop_first=True)
        print(df_encoded]
Out[2]:
          d  a_Var2  a_Var3  b_Var2  b_Var3  c_Var2  c_Var3
0  0.953153       0       1       0       1       0       1
1  0.924896       0       0       1       0       0       0
2  0.273205       1       0       1       0       1       0
3  0.459676       1       0       0       0       0       1
4  0.114358       1       0       0       0       0       0

Trong ứng dụng cụ thể của bạn, bạn sẽ phải cung cấp một danh sách các cột là Phân loại hoặc bạn sẽ phải suy ra các cột nào là Phân loại.

Kịch bản trường hợp tốt nhất khung dữ liệu của bạn đã có các cột này với một dtype=categoryvà bạn có thể chuyển columns=df.columns[df.dtypes == 'category']đến get_dummies.

dtypeMặt khác, tôi khuyên bạn nên đặt tất cả các cột khác là phù hợp (gợi ý: pd.to_numeric, pd.to_datetime, v.v.) và bạn sẽ được để lại các cột có hình objectchữ nhật và đây sẽ là các cột phân loại của bạn.

Các cột tham số pd.get_dummies mặc định như sau:

columns : list-like, default None
    Column names in the DataFrame to be encoded.
    If `columns` is None then all the columns with
    `object` or `category` dtype will be converted.

2

Để chuyển đổi nhiều loại cột cùng một lúc, tôi sẽ sử dụng một cái gì đó như thế này:

df2 = df.select_dtypes(include = ['type_of_insterest'])

df2[df2.columns].apply(lambda x:x.astype('category'))

Sau đó tôi sẽ tham gia cùng họ trở lại original df.


Tôi nghĩ df2[df2.columns] = df2[df2.columns].astype('category')làm như vậy, không apply, không lambda.
paulperry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.