2013-02-22 45 views
12

我正在嘗試使用UCI存儲庫中的汽車評估數據集,並且我想知道是否有方便的方式將sklearn中的分類變量二進制化。一種方法是使用LabelBinarizer的DictVectorizer,但在這裏我得到了k個不同的特徵,而您應該只有k-1以避免共線化。 我想我可以編寫自己的函數並刪除一列,但這個簿記是乏味的,是否有一個簡單的方法來執行這種轉換,並得到一個稀疏矩陣?如何在sklearn中對分類變量進行編碼?

+0

是否有一個特別的原因,你爲什麼喜歡k-1功能比k?具有k個特徵使得係數的解釋(比如在線性模型中)更容易並且可以促進稀疏特徵。 – 2013-02-23 14:37:56

+1

我試圖找到係數的相關性,並遇到共線性問題http://en.wikipedia.org/wiki/Multicollinearity – tonicebrian 2013-02-25 09:29:25

+0

我想我不足以進入事物的統計方面,看看爲什麼這會是一個問題。我會想象k特徵編碼在特徵相關性方面比任何其他編碼方法提供更多有意義的結果。 – 2013-02-25 14:03:23

回答

15

DictVectorizer是生成分類變量的單熱編碼的推薦方式;您可以使用sparse參數來創建稀疏的CSR矩陣,而不是密集的numpy陣列。我通常不關心多重共線性,我沒有注意到我傾向於使用的方法(即LinearSVC,SGDClassifier,基於樹的方法)的問題。

將DictVectorizer修補爲每個分類特徵刪除一列應該不成問題 - 您只需在fit方法的末尾從DictVectorizer.vocabulary中刪除一個項即可。 (拉請求我們隨時歡迎您!)

+5

是否有什麼特別的原因可以推薦您使用OneHotEncoder類的DictVectorizer? – Dexter 2013-07-05 14:25:31

+5

DictVectorizer更通用 - OneHotEncoder輸入僅限於表示類別的整數列。 DictVectorizer還處理文本分類值。另一方面,如果你所擁有的只是整數類別,OneHotEncoder看起來是最簡單的選擇。 – 2013-10-25 23:07:50

+1

但是爲了使用DictVectorizer,我需要將數組轉換爲列表中的每個字典中對應於數組中行的每個字典的字典列表。這看起來像一個黑客。爲什麼我不能將數組傳遞給DictVectorizer? – Ben 2015-12-03 16:38:11

16

的基本方法是

import numpy as np 
import pandas as pd, os 
from sklearn.feature_extraction import DictVectorizer 

def one_hot_dataframe(data, cols, replace=False): 
    vec = DictVectorizer() 
    mkdict = lambda row: dict((col, row[col]) for col in cols) 
    vecData = pd.DataFrame(vec.fit_transform(data[cols].apply(mkdict, axis=1)).toarray()) 
    vecData.columns = vec.get_feature_names() 
    vecData.index = data.index 
    if replace is True: 
     data = data.drop(cols, axis=1) 
     data = data.join(vecData) 
    return (data, vecData, vec) 

data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 
     'year': [2000, 2001, 2002, 2001, 2002], 
     'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} 

df = pd.DataFrame(data) 

df2, _, _ = one_hot_dataframe(df, ['state'], replace=True) 
print df2 

這裏是如何在稀疏格式

import numpy as np 
import pandas as pd, os 
import scipy.sparse as sps 
import itertools 

def one_hot_column(df, cols, vocabs): 
    mats = []; df2 = df.drop(cols,axis=1) 
    mats.append(sps.lil_matrix(np.array(df2))) 
    for i,col in enumerate(cols): 
     mat = sps.lil_matrix((len(df), len(vocabs[i]))) 
     for j,val in enumerate(np.array(df[col])): 
      mat[j,vocabs[i][val]] = 1. 
     mats.append(mat) 

    res = sps.hstack(mats) 
    return res 

data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 
     'year': ['2000', '2001', '2002', '2001', '2002'], 
     'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} 

df = pd.DataFrame(data) 
print df 

vocabs = [] 
vals = ['Ohio','Nevada'] 
vocabs.append(dict(itertools.izip(vals,range(len(vals))))) 
vals = ['2000','2001','2002'] 
vocabs.append(dict(itertools.izip(vals,range(len(vals))))) 

print vocabs 

print one_hot_column(df, ['state','year'], vocabs).todense() 
+2

這種方法如何處理新數據中看不見的值? – marbel 2016-12-14 02:13:26

31

做,如果你的數據是大熊貓數據框,那麼你可以簡單調用get_dummies。 假設您的數據框是df,並且您希望每個級別的變量'key'都有一個二進制變量。您可以簡單地撥打:

pd.get_dummies(df['key']) 

然後刪除其中一個虛擬變量,以避免多重共線性問題。 我希望這可以幫助...

+5

個人而言,我更喜歡熊貓的get_dummies來自sklearn的OneHotEncoder或DictVectorizer。在熊貓中使用get_dummies通常會導致更簡化的過程和更少的代碼。就我而言,熊貓更多的是關於數據分析和預處理,而sklearn更多的是關於繁重的「學習」過程。 – luanjunyi 2014-06-10 00:53:30

+19

get_dummies的缺點是它不一定會在得分數據集上產生相同的虛擬列(當您嘗試對一個模型進行評分時,會給您帶來很大的複雜性) – Chris 2016-01-15 20:54:39

+1

一種方法是首先進行concat培訓並測試DataFrame,然後應用get_dummies,最後分開培訓和測試DataFrame。這樣,培訓和測試數據將具有一致的熱門編碼。 – weidongxu 2017-06-02 13:42:07

相關問題