onehotencoder multiple get_dummies dummies drop columns python pandas machine-learning dummy-variable

python - multiple - Variables ficticias cuando no todas las categorías están presentes



pandas join (7)

Tengo un conjunto de marcos de datos donde una de las columnas contiene una variable categórica. Me gustaría convertirlo a varias variables ficticias, en cuyo caso normalmente usaría get_dummies .

Lo que sucede es que get_dummies analiza los datos disponibles en cada marco de datos para averiguar cuántas categorías hay y, por lo tanto, crea el número apropiado de variables ficticias. Sin embargo, en el problema en el que estoy trabajando ahora, sé de antemano cuáles son las categorías posibles. Pero al mirar cada marco de datos individualmente, no todas las categorías aparecen necesariamente.

Mi pregunta es: ¿hay alguna forma de pasar a get_dummies (o una función equivalente) los nombres de las categorías, de modo que, para las categorías que no aparecen en un marco de datos dado, simplemente crearía una columna de 0?

Algo que haría esto:

categories = [''a'', ''b'', ''c''] cat 1 a 2 b 3 a

Conviértete en esto:

cat_a cat_b cat_c 1 1 0 0 2 0 1 0 3 1 0 0


¿hay alguna manera de pasar a get_dummies (o una función equivalente) los nombres de las categorías, de modo que, para las categorías que no aparecen en un marco de datos dado, solo crearía una columna de 0?

¡Sí hay! Pandas tiene un tipo especial de serie solo para datos categóricos . Uno de los atributos de esta serie son las posibles categorías, que get_dummies tiene en cuenta. Aquí hay un ejemplo:

In [1]: import pandas as pd In [2]: possible_categories = list(''abc'') In [3]: cat = pd.Series(list(''aba'')) In [4]: cat = cat.astype(''category'', categories=possible_categories) In [5]: cat Out[5]: 0 a 1 b 2 a dtype: category Categories (3, object): [a, b, c]

¡Entonces, get_dummies hará exactamente lo que quieras!

In [6]: pd.get_dummies(cat) Out[6]: a b c 0 1 0 0 1 0 1 0 2 1 0 0

Hay muchas otras formas de crear una Series o un DataFrame , esta es la que me parece más conveniente. Puedes leer sobre todos ellos en la documentación de los pandas .

EDITAR:

No he seguido las versiones exactas, pero hubo un bug en cómo los pandas tratan las matrices dispersas, al menos hasta la versión 0.17.0. Fue corregido por la versión 0.18.1 (lanzada en mayo de 2016).

Para la versión 0.17.0, si intenta hacer esto con la opción sparse=True con un DataFrame , la columna de ceros para la variable ficticia faltante será una columna de NaN y se convertirá en densa.


Agregar la categoría que falta en el conjunto de prueba:

# Get missing columns in the training test missing_cols = set( train.columns ) - set( test.columns ) # Add a missing column in test set with default value equal to 0 for c in missing_cols: test[c] = 0 # Ensure the order of column in the test set is in the same order than in train set test = test[train.columns]

Tenga en cuenta que este código también elimina la columna resultante de la categoría en el conjunto de datos de prueba pero no está presente en el conjunto de datos de entrenamiento


No creo que get_dummies proporcione esto fuera de la caja, solo permite crear una column adicional que resalta los valores de NaN .

Para agregar las columns faltan, puede usar pd.concat largo de axis=0 para ''apilar'' verticalmente los DataFrames (las columnas ficticias más un id DataFrame ) y crear automáticamente las columnas faltantes, use fillna(0) para reemplazar los valores faltantes y luego use .groupby(''id'') para separar nuevamente los distintos DataFrame .


Pregunté esto en los pandas github. Resulta que es muy fácil evitarlo cuando define la columna como Categorical donde define todas las categorías posibles.

df[''col''] = pd.Categorical(df[''col''], categories=[''a'', ''b'', ''c'', ''d''])

get_dummies() hará el resto como se esperaba.


Prueba esto:

In[1]: import pandas as pd cats = ["a", "b", "c"] In[2]: df = pd.DataFrame({"cat": ["a", "b", "a"]}) In[3]: pd.concat((pd.get_dummies(df.cat, columns=cats), pd.DataFrame(columns=cats))).fillna(0) Out[3]: a b c 0 1.0 0.0 0 1 0.0 1.0 0 2 1.0 0.0 0


Según lo sugerido por otros, la conversión de sus características categóricas al tipo de datos ''categoría'' debería resolver el problema de la etiqueta invisible usando '' get_dummies ''.

# Your Data frame(df) from sklearn.model_selection import train_test_split X = df.loc[:,df.columns !=''label''] Y = df.loc[:,df.columns ==''label''] # Split the data into 70% training and 30% test X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3) # Convert Categorical Columns in your data frame to type ''category'' for col in df.select_dtypes(include=[np.object]).columns: X_train[col] = X_train[col].astype(''category'', categories = df[col].unique()) X_test[col] = X_test[col].astype(''category'', categories = df[col].unique()) # Now, use get_dummies on training, test data and we will get same set of columns X_train = pd.get_dummies(X_train,columns = ["Categorical_Columns"]) X_test = pd.get_dummies(X_test,columns = ["Categorical_Columns"])


Usar transposición y reindexar

import pandas as pd cats = [''a'', ''b'', ''c''] df = pd.DataFrame({''cat'': [''a'', ''b'', ''a'']}) dummies = pd.get_dummies(df, prefix='''', prefix_sep='''') dummies = dummies.T.reindex(cats).T.fillna(0) print dummies a b c 0 1.0 0.0 0.0 1 0.0 1.0 0.0 2 1.0 0.0 0.0