python - machine - ¿Cómo codificar una variable categórica en sklearn?
pandas categorical to numerical (3)
DictVectorizer es la forma recomendada de generar una codificación única de variables categóricas; puede usar el argumento sparse
para crear una matriz CSR dispersa en lugar de una matriz numpy densa. Por lo general, no me importa la multicolinealidad y no he notado un problema con los enfoques que suelo usar (es decir, LinearSVC, SGDClassifier, métodos basados en árbol).
No debería ser un problema parchear el DictVectorizer para eliminar una columna por cada característica categórica; simplemente necesita eliminar un término de DictVectorizer.vocabulary
al final del método de fit
. (¡Las solicitudes de extracción siempre son bienvenidas!)
Intento utilizar el conjunto de datos de evaluación de automóviles del repositorio UCI y me pregunto si existe una forma conveniente de binarizar variables categóricas en sklearn. Un enfoque sería usar el DictVectorizer de LabelBinarizer, pero aquí obtengo k funciones diferentes, mientras que debería tener solo k-1 para evitar la colinealización. Supongo que podría escribir mi propia función y soltar una columna, pero esta contabilidad es tediosa, ¿hay alguna manera fácil de realizar esas transformaciones y obtener como resultado una matriz dispersa?
si sus datos son un DataFrame de pandas, entonces simplemente puede llamar a get_dummies. Suponga que su marco de datos es df, y desea tener una variable binaria por nivel de variable ''clave''. Simplemente puede llamar:
pd.get_dummies(df[''key''])
y luego borre una de las variables ficticias para evitar el problema de colinealidad múltiple. Espero que esto ayude ...
El método básico es
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
Aquí está cómo hacerlo en formato disperso
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()