3
votes

Spécifier efficacement plusieurs noms de colonnes avec le même préfixe

J'exécute une régression avec mon observation au niveau de l'entreprise. Je veux contrôler le type d'entreprise [que produit-elle]. J'ai ces informations dans une variable d'objet que je transforme en catégorielle et en retire les mannequins.

reg = sm.OLS(endog=df['Y'], exog= df[['X1', 'Number of workers', 'X2', "Product Type_Jewellery", "Product_Type_Apparel", (all the other product dummies) ]], missing='drop')

Mon échantillon est assez volumineux et je finis par avoir beaucoup de variables factices. C'est pas mal de travail de les introduire dans mon modèle un par un (il peut y en avoir 10 à 15).

df['Product Type'] = df['Product Type'].astype('category')
df =  pd.get_dummies(df, columns=['Product Type']).head()  

Existe-t-il un moyen plus efficace de le faire? Dans les stata, j'ai utilisé le préfixe i.Product_Type qui signalerait au logiciel que la variable String devait être considérée comme une variable catégorielle ... quelque chose de similaire?


3 commentaires

Puisque vous mentionnez les stata, vous devez être très explicite avec statsmodels . Avec votre fonction OLS actuelle, vous n'avez pas de terme d'interception et vous utiliserez l'ensemble complet des catégories. Stata inclurait généralement l'interception et abandonnerait à la place l'une des catégories comme catégorie de référence.


merci beaucoup, je n'en étais pas au courant, comment puis-je laisser statsmodel calculer l'interception?


Le moyen le plus simple est d'ajouter une colonne de tous les 1 appelés 'intercept' à exog, quelque chose comme subset.assign (intercept = 1) va travailler dans la solution de coldspeed. Mais vous rencontrez ensuite un problème de colinéarité, vous devez donc supprimer manuellement l'une des catégories de produits vous-même.


3 Réponses :


2
votes

Utilisez str.contains pour trouver les colonnes qui contiennent "Product_ *", et y accéder devient facile.

subset = df[['X1', 'Number of workers', 'X2', *c]]
reg = sm.OLS(endog=df['Y'], exog=subset, missing='drop')

Si regex n'est pas nécessaire, vous pouvez initialiser c comme

c = [c_ for c_ in df if c_.startswith('Product')]

Ou, en utilisant str.startswith:

c = df.columns[df.columns.str.startswith('Product')]


0 commentaires

2
votes

Même idée que celle fournie à froid en utilisant filter

sm.OLS(endog=df['Y'], 
       exog=df.filter(regex=r'X1|X2|Number|Product'), 
       missing='drop')


0 commentaires

1
votes

En utilisant statsmodels.formula.api , vous n'avez pas besoin de générer les mannequins vous-même. Supprimez les espaces de vos noms de colonne et référencez la colonne catégorielle avec C(col_name)

========================================================================================
                           coef    std err          t      P>|t|      [0.025      0.975]
----------------------------------------------------------------------------------------
Intercept               69.2836     23.105      2.999      0.003      23.711     114.856
C(Product_Type)[T.b]    11.3334      6.941      1.633      0.104      -2.356      25.023
C(Product_Type)[T.c]     1.3745      6.943      0.198      0.843     -12.321      15.070
C(Product_Type)[T.d]     2.0430      6.258      0.326      0.744     -10.300      14.386
C(Product_Type)[T.e]     3.8445      6.273      0.613      0.541      -8.528      16.217
X1                       0.0207      0.113      0.184      0.854      -0.202       0.243
X2                       1.4677      2.177      0.674      0.501      -2.825       5.761
Number_of_workers       -0.5803      0.369     -1.573      0.117      -1.308       0.147
==============================================================================

Exemple de données

import pandas as pd
import numpy as np
np.random.seed(123)
df = pd.DataFrame({'Y': np.random.randint(1,100,200),
                   'X1': np.random.normal(1,20,200),
                   'X2': np.random.normal(-10,1,200),
                   'Number of workers': np.arange(1,201,1)/10,
                   'Product Type': np.random.choice(list('abcde'), 200)})


0 commentaires