¿Cómo se puede crear una matriz de diseño de interacción a partir de variables categóricas?

Vengo principalmente de trabajar en R para el modelado estadístico / aprendizaje automático y busco mejorar mis habilidades en Python. Me pregunto cuál es la mejor manera de crear una matriz de diseño de interacciones categóricas (en grado arbitrario) en python.

Un ejemplo de juguete:

import pandas as pd from urllib import urlopen page = urlopen("http://www.shatterline.com/MachineLearning/data/tennis_anyone.csv") df = pd.read_csv(page) df.head(n=5) 

introduzca la descripción de la imagen aquí

Digamos que queremos crear interacciones entre Outlook, Temp y Humedad. ¿Hay una manera eficiente de hacer esto? Puedo hacer manualmente algo como esto en pandas:

 OutTempFact=pd.Series(pd.factorize(pd.lib.fast_zip([df.Outlook.values, df.Temperature.values]))[0],name='OutTemp') OutHumFact=pd.Series(pd.factorize(pd.lib.fast_zip([df.Outlook.values, df.Humidity.values]))[0],name='OutHum') TempHumFact=pd.Series(pd.factorize(pd.lib.fast_zip([df.Temperature.values, df.Humidity.values]))[0],name='TempHum') IntFacts=pd.concat([OutTempFact,OutHumFact,TempHumFact],axis=1) IntFacts.head(n=5) 

introduzca la descripción de la imagen aquí

que luego podría pasar a un codificador de scikit-learn one-hot, pero es probable que haya una forma mucho mejor y menos manual de crear interacciones entre variables categóricas sin tener que pasar por cada combinación.

 import sklearn as sk enc = sk.preprocessing.OneHotEncoder() IntFacts_OH=enc.fit_transform(IntFacts) IntFacts_OH.todense() 

Si utiliza OneHotEncoder en su matriz de diseño para obtener una matriz de diseño de primera calidad, las interacciones no son más que multiplicaciones entre columnas. Si X_1hot es su matriz de diseño único, donde las muestras son líneas, para las interacciones de segundo orden puede escribir

 X_2nd_order = (X_1hot[:, np.newaxis, :] * X_1hot[:, :, np.newaxis]).reshape(len(X_1hot), -1) 

Habrá duplicados de interacciones y también contendrá las características originales.

Ir a un orden arbitrario hará que su matriz de diseño explote. Si realmente quieres hacer eso, entonces deberías estudiar la kernelización con un núcleo polinomial, que te permitirá ir a grados arbitrarios fácilmente.

Usando el dataframe que presenta, podemos proceder de la siguiente manera. Primero, una forma manual de construir un diseño de un solo calor a partir del dataframe:

 import numpy as np indicators = [] state_names = [] for column_name in df.columns: column = df[column_name].values one_hot = (column[:, np.newaxis] == np.unique(column)).astype(float) indicators.append(one_hot) state_names = state_names + ["%s__%s" % (column_name, state) for state in np.unique(column)] X_1hot = np.hstack(indicators) 

Los nombres de las columnas se almacenan luego en los state_names y la matriz del indicador es X_1hot . Luego calculamos las características de segundo orden.

 X_2nd_order = (X_1hot[:, np.newaxis, :] * X_1hot[:, :, np.newaxis]).reshape(len(X_1hot), -1) 

Para conocer los nombres de las columnas de la matriz de segundo orden, las construimos así.

 from itertools import product one_hot_interaction_names = ["%s___%s" % (column1, column2) for column1, column2 in product(state_names, state_names)] 

Al enfrentarme ahora a un problema similar de querer una forma fácil de integrar interacciones específicas de un modelo OLS de referencia de la literatura para compararlas con los enfoques de ML, encontré a Patsy ( http://patsy.readthedocs.io/en/latest/overview .html ) y esta patsylearn de integración de scikit -learn ( https://github.com/amueller/patsylearn ).

A continuación, cómo se pueden pasar las variables de interacción al modelo:

 from patsylearn import PatsyModel model = PatsyModel(sk.linear_model.LinearRegression(), "Play-Tennis ~ C(Outlook):C(Temperature) + C(Outlook):C(Humidity) + C(Outlook):C(Wind)") 

Tenga en cuenta que, en esta formulación, no necesita el OneHotEncoder (), ya que la C en la fórmula le dice al intérprete de Patsy que estas son variables categóricas y que están codificadas de forma instantánea para usted. Pero lea más sobre esto en su documentación ( http://patsy.readthedocs.io/en/latest/categorical-coding.html ).

O, también puede usar el PatsyTransformer, que prefiero, ya que permite una fácil integración en las tuberías de scikit-learn:

 from patsylearn import PatsyTransformer transformer = PatsyTransformer("C(Outlook):C(Temperature) + C(Outlook):C(Humidity) + C(Outlook):C(Wind)")