處理分類型特征:編碼與啞變量
在機器學習中,大多數算法,譬如邏輯回歸,支持向量機SVM,k近鄰算法等都只能夠處理數值型數據,不能處理
文字,在sklearn當中,除了專用來處理文字的算法,其他算法在fifit的時候全部要求輸入數組或矩陣,也不能夠導
入文字型數據(其實手寫決策樹和普斯貝葉斯可以處理文字,但是sklearn中規定必須導入數值型)。
然而在現實中,許多標簽和特征在數據收集完畢的時候,都不是以數字來表現的。比如說,學歷的取值可以是["小
學",“初中”,“高中”,"大學"],付費方式可能包含["支付寶",“現金”,“微信”]等等。在這種情況下,為了讓數據適
應算法和庫,我們必須將數據進行編碼,即是說,將文字型數據轉換為數值型。
一、sklearn中的處理啞變量方法
1.preprocessing.LabelEncoder:標簽專用,能夠將分類轉換為分類數值
1 data = pd.DataFrame([ '司機', '農業技術人員', '臨時工', '種植業生產人員', '教師']) 2 encoder = LabelEncoder() #要輸入的是標簽,不是特征矩陣,所以允許一維 3 encoder = encoder.fit(data.iloc[:,-1])#導入數據 4 result = encoder.transform(data.iloc[:,-1])#transform接口調取結果 5 6 encoder.classes_#屬性.classes_查看標簽中究竟有多少類別 7 result#查看獲取的結果 8 9 encoder.inverse_transform(result )#使用inverse_transform可以逆轉 10 11 #一步簡寫 12 data.iloc[:,-1] = LabelEncoder().fit_transform(data.iloc[:,-1])#
輸出結果:
result:
array([2, 1, 0, 4, 3])#這里輸出為一維矩陣
2.preprocessing.OrdinalEncoder:特征專用,能夠將分類特征轉換為分類數值
1 from sklearn.preprocessing import OrdinalEncoder 2 data = pd.DataFrame([ '司機', '農業技術人員', '臨時工', '種植業生產人員', '教師']) 3 x = data.iloc[:,-1].values.reshape(-1,1)#轉置為二維矩陣 4 OrdinalEncoder().fit(x).categories_#查看有多少分類 5 OrdinalEncoder().fit_transform(x)#轉換為二維矩陣
輸出結果:
array([[2.], [1.], [0.], [4.], [3.]])#與上面不同的是這里為二維矩陣
3.preprocessing.OneHotEncoder:獨熱編碼,創建啞變量
我們來思考三種不同性質的分類數據:
1) 艙門(S,C,Q)
三種取值S,C,Q是相互獨立的,彼此之間完全沒有聯系,表達的是S≠C≠Q的概念。這是名義變量。
2) 學歷(小學,初中,高中)
三種取值不是完全獨立的,我們可以明顯看出,在性質上可以有高中>初中>小學這樣的聯系,學歷有高低,但是學
歷取值之間卻不是可以計算的,我們不能說小學 + 某個取值 = 初中。這是有序變量。
3) 體重(>45kg,>90kg,>135kg)
各個取值之間有聯系,且是可以互相計算的,比如120kg - 45kg = 90kg,分類之間可以通過數學計算互相轉換。這
是有距變量。
對特征進行編碼的時候,這三種分類數據都會被我們轉換為[0,1,2],這三個數字在算法看來,是連續且可以
計算的,這三個數字相互不等,有大小,並且有着可以相加相乘的聯系。所以算法會把艙門,學歷這樣的分類特
征,都誤會成是體重這樣的分類特征。這是說,我們把分類轉換成數字的時候,忽略了數字中自帶的數學性質,所
以給算法傳達了一些不准確的信息,而這會影響我們的建模。
類別OrdinalEncoder可以用來處理有序變量,但對於名義變量,我們只有使用啞變量的方式來處理,才能夠盡量
向算法傳達最准確的信息:
1 from sklearn.preprocessing import OneHotEncoder 2 data = pd.DataFrame([ '司機', '農業技術人員', '臨時工', '種植業生產人員', '教師'],columns=['occupation']) 3 X = data.iloc[:,-1].values.reshape(-1,1)#轉換為二維矩陣 4 enc = OneHotEncoder(categories='auto').fit(X)#擬合 5 result = enc.transform(X).toarray()#輸出轉化值 6 7 輸出結果: 8 array([[0., 0., 1., 0., 0.], 9 [0., 1., 0., 0., 0.], 10 [1., 0., 0., 0., 0.], 11 [0., 0., 0., 0., 1.], 12 [0., 0., 0., 1., 0.]]) 13 14 OneHotEncoder(categories='auto').fit_transform(X).toarray()#一步到位 15 16 enc.inverse_transform(result)#還原結果 17 輸出結果: 18 array([['司機'], 19 ['農業技術人員'], 20 ['臨時工'], 21 ['種植業生產人員'], 22 ['教師']], dtype=object) 23 24 enc.get_feature_names()#獲取轉換后數值的標簽 25 輸出結果 26 array(['x0_臨時工', 'x0_農業技術人員', 'x0_司機', 'x0_教師', 'x0_種植業生產人員'], 27 dtype=object) 28 29 #axis=1,表示跨行進行合並,也就是將量表左右相連,如果是axis=0,就是將量表上下相連 30 newdata = pd.concat([data,pd.DataFrame(result)],axis=1)
二、pandas中
方法一、pd.get_dummies( data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None,)
1 data = [ '司機', '農業技術人員', '臨時工', '種植業生產人員', '教師'] 2 data = pd.DataFrame(data,columns=['occupation']) 3 data_dummis=pd.get_dummies(data) 4 data_dummis
輸出結果:
方法二:pd.factorize
1 data_factorize = pd.factorize(data['occupation'])#只能填寫一列 2 data_factorize
輸出結果:為數組類型
1 (array([0, 1, 2, 3, 4], dtype=int64), 2 Index(['司機', '農業技術人員', '臨時工', '種植業生產人員', '教師'], dtype='object'))
1 data['factorize'] = pd.DataFrame(data_factorize[0])
擴展:(來源:菜菜老師)