2 votes

Équivalent des macros Stata en Python

Je suis en train d'utiliser Python pour l'analyse statistique.

Dans Stata je peux définir des macros locales et de développer en tant que de besoin:

program define reg2
    syntax varlist(min=1 max=1), indepvars(string) results(string)
    if "`results'" == "y" {
        reg `varlist' `indepvars'
    }
    if "`results'" == "n" {
        qui reg `varlist' `indepvars'
    }
end

sysuse auto, clear

Ainsi, au lieu de:

reg2 mpg, indepvars("weight foreign price") results("y")

J'ai pu faire:

local options , indepvars(weight foreign price) results(y) 
reg2 mpg `options'

Ou encore:

local vars weight foreign price
local options , indepvars(`vars') results(y) 
reg2 mpg `options'

Les Macros dans Stata m'aider à rédiger propres scripts, sans répéter le code.

En Python, j'ai essayé de la chaîne d'interpolation, mais cela ne fonctionne pas dans les fonctions.

Par exemple:

def reg2(depvar, indepvars, results):
    print(depvar)
    print(indepvars)
    print(results)

La suite se passe bien:

reg2('mpg', 'weight foreign price', 'y')

Cependant, ces deux échouer:

regargs = 'mpg', 'weight foreign price', 'y'
reg2(regargs)

regargs = 'depvar=mpg, covariates=weight foreign price, results=y'
reg2(regargs)

J'ai trouvé une question similaire, mais il n'a pas répondu à ma question:

Il existe également une autre question à ce sujet pour la R:

Cependant, je ne pouvais pas trouver quoi que ce soit pour Python en particulier.

Je me demandais si il n'y a rien en Python qui est similaire à Stata macros?

79voto

Pearly Spencer Points 6670

Faire de la Pythonic façon.

L'utilisation généralisée des macros dans Stata témoigne d'une autre philosophie de programmation. Contrairement à Python, qui est un orientée objet, langage de programmation, Stata est ado langue (pas mata) nécessite des macros afin de fonctionner comme quelque chose de plus qu'un simple langage de script.

Les Macros peuvent être utilisés presque partout dans Stata (même dans les définitions de macros) pour deux raisons:

  1. Remplacement de texte
  2. L'évaluation de l'Expression

À l'aide de macros, l'utilisateur peut simplifier leur code, qui à son tour, permettra de réduire la le potentiel pour des erreurs et garder bien rangé. L'inconvénient est que l'utilisation de macros rend la syntaxe de la langue fluide.

Pour répondre à votre question, Pyexpander fournit une partie de ce type de fonctionnalité en Python, mais c'est pas vraiment une substitut. Pour les différents cas d'utilisation, vous aurez besoin d'une approche différente pour imiter macro d'extension. En contraste avec Stata, il n'y a pas d'uniforme façon de le faire partout.

Mon conseil est de vous familiariser avec Python conventions plutôt que de en essayant de programmer les choses de la "Stata façon". Par exemple, il est utile de rappeler que le local et le global macros dans Stata correspondent à des variables en Python (local dans une fonction, mondial à l'extérieur), tandis que les variables dans Stata correspondent à Pandas.Series ou une colonne d'un Pandas.DataFrame. De Même, Stata ado les programmes correspondent à des fonctions en Python.

La solution fournie dans l' @g.d.d.c est la réponse peut être un bon outil vers la réalisation de ce que quelqu'un voudrais. Cependant, des étapes supplémentaires sont requises ici si vous voulez ré-utiliser votre code.

À l'aide de votre jouet exemple:

import pandas as pd   
import numpy as np      
import statsmodels.api as sm

df = pd.read_stata('http://www.stata-press.com/data/r14/auto.dta')

In [1]: df[['mpg', 'weight', 'price']].head()
Out[1]: 
   mpg  weight  price
0   22    2930   4099
1   17    3350   4749
2   22    2640   3799
3   20    3250   4816
4   15    4080   7827

Supposons que vous voulez ré-utilisation de l'extrait de code suivant, mais avec différents variables:

In [2]: Y = df['mpg']
In [3]: df['cons'] = 1
In [4]: X = df[['weight', 'price', 'cons']]

In [5]: reg = sm.OLS(Y, X).fit()
In [6]: print(reg.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                    mpg   R-squared:                       0.653
Model:                            OLS   Adj. R-squared:                  0.643
Method:                 Least Squares   F-statistic:                     66.85
Date:                                   Prob (F-statistic):           4.73e-17
Time:                                   Log-Likelihood:                -195.22
No. Observations:                  74   AIC:                             396.4
Df Residuals:                      71   BIC:                             403.3
Df Model:                           2                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
weight        -0.0058      0.001     -9.421      0.000      -0.007      -0.005
price      -9.351e-05      0.000     -0.575      0.567      -0.000       0.000
cons          19.7198      0.811     24.322      0.000      18.103      21.336
==============================================================================
Omnibus:                       29.900   Durbin-Watson:                   2.347
Prob(Omnibus):                  0.000   Jarque-Bera (JB):               60.190
Skew:                           1.422   Prob(JB):                     8.51e-14
Kurtosis:                       6.382   Cond. No.                     1.50e+04
==============================================================================

Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.5e+04. This might indicate that there are
strong multicollinearity or other numerical problems.

Comment pourriez-vous le faire?

Tout d'abord, créez une fonction:

def reg2(depvar, indepvars, results, df):
    Y = df[depvar]
    df['cons'] = 1
    X = df[indepvars]

    reg = sm.OLS(Y, X).fit()
    if results != 0:
        print(reg.summary())

Toutefois, notez que, bien que la chaîne de l'interpolation peut 'étendre' chaînes, ici cette approche ne fonctionnera pas, car la fonction cible pour regresson analyse ne pas accepter un unifiée de la chaîne du genre 'weight, price, cons'.

Au lieu de cela, vous devez définir une liste avec les variables explicatives:

predictors = ['weight', 'price', 'cons']
reg2('mpg', predictors, 0, df)

Vous pouvez également prendre ce concept au niveau suivant par la construction d'un décorateur:

def load_and_reg2(func):
    def wrapper(*args, **kwargs):

        print()
        print("Loading the dataset...")
        print()

        df = pd.read_stata('http://www.stata-press.com/data/r14/auto.dta')
        sumvars = df[['mpg', 'weight', 'price']].head()
        print(sumvars)
        print()

        func(*args, **kwargs, df = df)
        return func(*args, **kwargs, df = df)

        print()
        print("Doing any other stuff you like...")
        print()

        dfshape = df.shape
        print('Shape:', dfshape)

    return wrapper

Et l'utiliser dans vos reg2() fonction de:

@load_and_reg2
def reg2(depvar, indepvars, results, df):
    Y = df[depvar]
    df['cons'] = 1
    X = df[indepvars]

    reg = sm.OLS(Y, X).fit()
    if results != 0:
        print(reg.summary())
    return reg

L'exemple est peut-être très simpliste, mais démontre la puissance de Python:

In [7]: [predictors = ['weight', 'price', 'cons']
In [8]: reg2('mpg', predictors, 1)

Loading the dataset...

   mpg  weight  price
0   22    2930   4099
1   17    3350   4749
2   22    2640   3799
3   20    3250   4816
4   15    4080   7827

                            OLS Regression Results                            
==============================================================================
Dep. Variable:                    mpg   R-squared:                       0.653
Model:                            OLS   Adj. R-squared:                  0.643
Method:                 Least Squares   F-statistic:                     66.85
Date:                                   Prob (F-statistic):           4.73e-17
Time:                                   Log-Likelihood:                -195.22
No. Observations:                  74   AIC:                             396.4
Df Residuals:                      71   BIC:                             403.3
Df Model:                           2                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
weight        -0.0058      0.001     -9.421      0.000      -0.007      -0.005
price      -9.351e-05      0.000     -0.575      0.567      -0.000       0.000
cons          39.4397      1.622     24.322      0.000      36.206      42.673
==============================================================================
Omnibus:                       29.900   Durbin-Watson:                   2.347
Prob(Omnibus):                  0.000   Jarque-Bera (JB):               60.190
Skew:                           1.422   Prob(JB):                     8.51e-14
Kurtosis:                       6.382   Cond. No.                     3.00e+04
==============================================================================

Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large,  3e+04. This might indicate that there are
strong multicollinearity or other numerical problems.

Doing any other stuff you like...

Shape: (74, 13)

Comme vous pouvez le voir, le décorateur d'autres résumés des choses, mais à l'aide fixe de la syntaxe.

Dans le Python univers des dictionnaires et des classes jouent aussi un rôle important dans la réutilisation de code/résultats. Par exemple, un dictionnaire peut agir comme l'équivalent de Stata est return de l'espace pour stocker plusieurs macros, des scalaires, etc.

Envisager le légèrement modifié la version de notre jouet décorateur load_and_reg2, ce qui enregistre désormais des objets individuels dans un dictionnaire, D , et le renvoie:

def load_and_reg2(func):
    def wrapper(*args, **kwargs):

        D = {}

        print()   
        print("Loading the dataset...")
        print()

        df = pd.read_stata('http://www.stata-press.com/data/r14/auto.dta')
        sumvars = df[['mpg', 'weight', 'price']].head()
        D['sumvars'] = sumvars
        print(sumvars)
        print()

        D['reg2'] = func(*args, **kwargs, df)

        print()
        print("Doing any other stuff you like...")

        print()                     
        dfshape = df.shape
        D['dfshape'] = dfshape              
        print('Shape:', dfshape)

        return D    

    return wrapper

Ensuite, vous pouvez facilement le faire:

In [9]: foo = reg2('mpg', predictors, 1)

In [10]: foo.keys()
Out[10]: dict_keys(['sumvars', 'reg2', 'dfshape'])

In [11]: foo['sumvars']
Out[11]: 
   mpg  weight  price
0   22    2930   4099
1   17    3350   4749
2   22    2640   3799
3   20    3250   4816
4   15    4080   7827

Les Classes peuvent introduire davantage de flexibilité dans le coût d'une complexité supplémentaire:

class loadreg2return(object):
    def __init__(self, sumvars=None, reg2=None, dfshape=None):
        self.sumvars = sumvars
        self.reg2 = reg2
        self.dfshape = dfshape

def load_and_reg2(func):
    def wrapper(*args, **kwargs):

        print("Loading the dataset...")
        print()

        df = pd.read_stata('http://www.stata-press.com/data/r14/auto.dta')
        sumvars = df[['mpg', 'weight', 'price']].head()
        print(sumvars)
        print()

        reg2 = func(*args, **kwargs, df = df)

        print()
        print("Doing any other stuff you like...")

        print()                     
        dfshape = df.shape
        loadreg2return(dfshape = dfshape)            
        print('Shape:', dfshape)

        return loadreg2return(sumvars = sumvars, reg2 = reg2, dfshape = dfshape )

    return wrapper

Cette version de notre jouet décorateur retourne:

In [12]: foo.dfshape
Out[12]: (74, 13)

In [13]: foo.sumvars
Out[13]: 
   mpg  weight  price
0   22    2930   4099
1   17    3350   4749
2   22    2640   3799
3   20    3250   4816
4   15    4080   7827

In [14]: foo.reg2.params
Out[14]: 
weight    -0.005818
price     -0.000094
cons      39.439656

dtype: float64

1voto

g.d.d.c Points 20164

Il semble que vous voulez juste le et les opérateurs pour les fonctions d’appel:

Utilisez pour étendre une liste ou tuple dans les arguments de position, ou utiliser pour étendre un dictionnaire dans les arguments de mots clés à une fonction qui les exige.

Pour votre exemple de mot clé, vous devez modifier un peu la déclaration :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X