web-dev-qa-db-ja.com

sklearnでカテゴリ変数をエンコードする方法は?

UCIリポジトリの自動車評価データセットを使用しようとしていますが、sklearnでカテゴリ変数を2値化する便利な方法があるかどうか疑問に思います。 1つのアプローチはLabelBinarizerのDictVectorizerを使用することですが、ここではk個の異なる機能を取得していますが、共線化を回避するにはk-1だけにする必要があります。独自の関数を記述して1つの列を削除できると思いますが、この簿記は面倒です。そのような変換を実行して、結果としてスパース行列を取得する簡単な方法はありますか?

12
tonicebrian

DictVectorizerは、カテゴリ変数のワンホットエンコーディングを生成するための推奨される方法です。 sparse引数を使用して、密なnumpy配列の代わりに疎なCSR行列を作成できます。私は通常、多重共線性を気にしません。また、私が使用する傾向のあるアプローチ(LinearSVC、SGDClassifier、ツリーベースのメソッドなど)に問題があることに気づいていません。

DictVectorizerにパッチを適用して、カテゴリ機能ごとに1つの列を削除することは問題ではありません。fitメソッドの最後にあるDictVectorizer.vocabularyから1つの用語を削除するだけです。 (プルリクエストはいつでも大歓迎です!)

15

データがpandas DataFrameの場合、get_dummiesを呼び出すだけです。データフレームがdfであり、変数 'key'のレベルごとに1つのバイナリ変数が必要であると想定します。単に呼び出す:

pd.get_dummies(df['key'])

次に、多重共線性の問題を回避するために、ダミー変数の1つを削除します。これがお役に立てば幸いです...

31
rezakhorshidi

基本的な方法は

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()
16
BBDynSys