[Measurement Economics](https://www.amazon.co.jp/ Quantitative Economics-New-Liberal-Arts-Selection / dp / 4641053855 / ref = asc_df_4641053855_nodl /? Tag = jpgo-22 & linkCode = df0 & hvadid = 342654745883 & hvpos = & hvn = g & hvrand = 3840609228244811524 & hvpone = & hvptwo = & hvqmt = & hvdev = m & hvdvcmdl = & hvlocint = & hvlocphy = 19009363 & hvtargid = pla-796815219068 & psc = 1 & th = 1) & psc = 1)
En gros, je fais des réponses en regardant les documents officiels des modèles de statistiques et des modèles linéaires, github. Je ne connais pas du tout python, donc si vous avez des erreurs, veuillez le signaler et demander.
Le problème à la fin du chapitre 8 est la reproduction des tableaux 8-1 et 8-5.
La reproduction du Tableau 8-1 nécessite le traitement lorsque la variable expliquée est une variable binaire. Nous comparerons le modèle de probabilité linéaire, le modèle probit et le modèle logit comme moyennes.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.set()
import statsmodels.api as sm
from statsmodels.formula.api import ols
from statsmodels.formula.api import logit, probit
#Lire et confirmer les données
df = pd.read_stata('piaac.dta')
df.head()
Dans l'analyse du tableau 8-1, [lfs] est limité aux femmes et est retourné à [éduc], [âge], [couple], [enfant]. Obtenez uniquement les colonnes et les enregistrements dont vous avez besoin.
df_1 = df[df['gender']== 'Female']
df_1 = df_1[['lfs','educ','age','couple','child']]
Le problème ici est que la variable expliquée [lfs] est une variable qualitative. Pour le moment, vérifions quelle valeur prend la variable expliquée.
#['lfs']Vérifiez le type de
df_1['lfs'].unique()
#[Employed, Out of the labour force, Unemployed, Not known]
Categories (4, object): [Employed < Unemployed < Out of the labour force < Not known]
#Vérifiez également l'âge
df_1['age'].unique()
#[45, 29, 35, 48, 60, ..., 41, 37, 19, 58, 28]
Length: 50
Categories (50, int64): [16 < 17 < 18 < 19 ... 62 < 63 < 64 < 65]
Lfs semble prendre quatre types de valeurs: Employé, Chômeur, Hors de la main-d'œuvre, Inconnu. Comment interpréter cela est une question très délicate par nature, mais le tableau 8-1 ne baisse pas. Inconnu et semble être considéré comme des personnes non actives. Que faire si la variable expliquée n'est pas observée (la sélection de l'échantillon devient un problème) sera prise en compte lors de la mise en œuvre du modèle Hekit. De plus, la population hors du marché du travail est littéralement une population non active, mais comme toutes les données ne concernent que les personnes de plus de 16 ans, elles peuvent travailler par nature. Cependant, je choisis de ne pas travailler pour une raison quelconque, comme les bas salaires offerts. Ici, nous allons considérer le cas où la variable expliquée prend une variable binaire, donc créez une variable fictive avec Employed = 1 et autre = 0 pour l'analyse.
#Colonne de variable factice['emp_dummy']Création
df_1.loc[df_1['lfs']=='Employed','emp_dummy']=1
df_1.loc[df_1['lfs']!='Employed','emp_dummy']=0
# Vérifiez le type de données au cas où
df_1.dtypes
#lfs category
educ category
age category
couple float32
child float32
emp_dummy float64
dtype: object
Pour une raison quelconque, l'éducation et l'âge sont catégoriques ... Convertissez en une variable numérique.
#Changer le type de données
df_1[['educ','age']] = df_1[['educ','age']].apply(pd.to_numeric)
Tout d'abord, ignorez les valeurs manquantes et effectuez l'analyse.
#Estimation OLS
result_1_1 = ols(formula = 'emp_dummy ~ educ + age + couple + child',
data = df_1).fit(cov_type='HC1',use_t=True)
Lorsque vous utilisez l'erreur standard de blanc de correction de liberté, spécifiez HC1 pour cov_type. Spécifiez HC0 pour utiliser l'erreur standard du blanc normal.
#Vérifiez le résultat
result_1_1.summary()
coef | std err | t | P>t | [0.025 | [0.025 | |
---|---|---|---|---|---|---|
Intercept | 0.3759 | 0.105 | 3.566 | 0.000 | 0.169 | 0.583 |
educ | 0.0195 | 0.006 | 3.312 | 0.001 | 0.008 | 0.031 |
age | 0.0020 | 0.001 | 1.726 | 0.085 | -0.000 | 0.004 |
couple | -0.1178 | 0.031 | -3.743 | 0.000 | -0.180 | -0.056 |
child | 0.0137 | 0.013 | 1.067 | 0.286 | -0.012 | 0.039 |
On peut dire que le résultat est exactement le même. Il semble que le tableau 8-1 du manuel ignore les valeurs manquantes pour l'analyse.
Je vais également l'analyser pour traiter les valeurs manquantes. C'est une question très délicate, mais pour l'instant, mettons la valeur moyenne.
#Remplissez les valeurs manquantes avec des valeurs moyennes
df_1['educ'] = df_1['educ'].fillna(df_1['educ'].mean())
df_1['age'] = df_1['age'].fillna(df_1['age'].mean())
df_1['couple'] = df_1['couple'].fillna(df_1['couple'].mean())
df_1['child'] = df_1['child'].fillna(df_1['couple'].mean())
#Estimation OLS
result_1_nonan = ols(formula = 'emp_dummy ~ educ + age + couple + child',
data = df_1).fit(cov_type='HC1',use_t=True)
#Vérifiez le résultat
result_1_nonan_summary()
chef | std err | t | P>t | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | 0.0189 | 0.062 | 0.302 | 0.763 | -0.104 | 0.141 |
educ | 0.0450 | 0.004 | 10.951 | 0.000 | 0.037 | 0.053 |
age | 0.0032 | 0.001 | 3.895 | 0.000 | 0.002 | 0.005 |
couple | -0.1035 | 0.022 | -4.735 | 0.000 | -0.146 | -0.061 |
child | -0.0006 | 0.009 | -0.059 | 0.953 | -0.019 | 0.018 |
La valeur a un peu changé. Après tout, dans l'analyse des manuels, il semble que tous les enregistrements, y compris les valeurs manquantes, soient supprimés et analysés.
À partir de là, suivez le manuel et ignorez toutes les valeurs manquantes.
#Mise en forme des données
df = pd.read_stata('piaac.dta')
df_2 = df[df['gender']== 'Female']
df_2 = df_2[['lfs','educ','age','couple','child']]
df_2.loc[df_2['lfs']=='Employed','emp_dummy']=1
df_2.loc[df_2['lfs']!='Employed','emp_dummy']=0
df_2[['educ','age']] = df_2[['educ','age']].apply(pd.to_numeric)
Si vous utilisez un modèle probit, vous pouvez simplement utiliser "probit" au lieu de "ols", si vous profitez des statsmodels.
###modèle probit
result_1_2 = probit(formula = 'emp_dummy ~ educ + age + couple + child',
data = df_2).fit()
#Vérifiez le résultat
result_1_2.summary().tables[1]
coef | std err | z | P>z | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | -0.3443 | 0.287 | -1.198 | 0.231 | -0.908 | 0.219 |
educ | 0.0537 | 0.016 | 3.340 | 0.001 | 0.022 | 0.085 |
age | 0.0053 | 0.003 | 1.789 | 0.074 | -0.001 | 0.011 |
couple | -0.3391 | 0.097 | -3.489 | 0.000 | -0.530 | -0.149 |
child | 0.0397 | 0.032 | 1.256 | 0.209 | -0.022 | 0.102 |
Cette fois, le résultat est presque le même que celui du tableau 8-1.
Vient ensuite le calcul de l'effet marginal. Si vous utilisez statsmodels, l'effet marginal du modèle Probit est terminé avec la méthode "get_margeff".
#Effet marginal
result_1_2.get_margeff().summary().tables[1]
dy/dx | std err | z | P>z | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
educ | 0.0197 | 0.006 | 3.372 | 0.001 | 0.008 | 0.031 |
age | 0.0019 | 0.001 | 1.794 | 0.073 | -0.000 | 0.004 |
couple | -0.1243 | 0.035 | -3.524 | 0.000 | -0.193 | -0.055 |
child | 0.0145 | 0.012 | 1.258 | 0.209 | -0.008 | 0.037 |
C'est le même résultat que le manuel.
Tout comme avec Probit, vous utilisez simplement "logit". L'effet marginal peut être calculé de la même manière avec le module "get_margeff".
#Modèle Logit
result_1_4 = logit(formula = 'emp_dummy ~ educ + age + couple + child',
data = df_2).fit()
#Vérifiez le résultat
result_1_4.summary().tables[1]
#Effet marginal
result_1_4.get_margeff().summary().tables[1]
coef | std err | z | P>z | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | -0.5781 | 0.471 | -1.227 | 0.220 | -1.502 | 0.345 |
educ | 0.0869 | 0.026 | 3.307 | 0.001 | 0.035 | 0.138 |
age | 0.0088 | 0.005 | 1.806 | 0.071 | -0.001 | 0.018 |
couple | -0.5587 | 0.163 | -3.424 | 0.001 | -0.879 | -0.239 |
child | 0.0716 | 0.058 | 1.242 | 0.214 | -0.041 | 0.185 |
dy/dx | std err | z | P>z | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
educ | 0.0195 | 0.006 | 3.345 | 0.001 | 0.008 | 0.031 |
age | 0.0020 | 0.001 | 1.812 | 0.070 | -0.000 | 0.004 |
couple | -0.1255 | 0.036 | -3.463 | 0.001 | -0.197 | -0.054 |
child | 0.0161 | 0.013 | 1.244 | 0.213 | -0.009 | 0.041 |
statsmodels a une classe utile "GenericLikelihoodModel", qui dit officiellement The GenericLikelihoodModel class eases the process by providing tools such as automatic numeric differentiation and a unified interface to scipy optimization functions. Using statsmodels, users can fit new MLE models simply by “plugging-in” a log-likelihood function.
Il semble que ce soit pratique lorsque vous souhaitez estimer le maximum de vraisemblance à l'aide d'une fonction de vraisemblance maison.
Étant donné que l'exemple du document officiel n'est mis en œuvre qu'en modifiant l'ensemble de données, veuillez également vous reporter au document officiel.
#importer
from scipy import stats
from statsmodels.base.model import GenericLikelihoodModel
#Supprimer les enregistrements contenant des valeurs manquantes
df_4 = df_2.dropna()
#Créez une matrice de variables explicatives.
exog = df_4.loc[:,['educ','age','couple','child']]
exog = sm.add_constant(exog,prepend=True)
#Créez un vecteur de variables expliquées.
endog = df_4.loc[:,'emp_dummy']
Si la variable latente est déterminée par la formule de droite, $ Y_ {i} ^ {*} = X_ {i} '\ beta + e_ {i} $ Modèle de sélection binaire La fonction de vraisemblance générale de type log est
Donc, tout ce que vous avez à faire est de changer F () en une fonction de distribution normalement distribuée et de vous y plonger.
class MyProbit(GenericLikelihoodModel):
def loglike(self,params):
exog = self.exog
endog = self.endog
q= 2*endog-1
return stats.norm.logcdf(q*np.dot(exog,params)).sum()#Log de la probabilité du modèle Probit
Il semble que vous puissiez estimer avec juste cela.
#Adapté au modèle Probit
result_mine = MyProbit(endog, exog).fit(maxiter=1000)
#Vérifiez le résultat
result_mine.summary().tables[1]
chef | stderr | z | P>z | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
const | -0.3444 | 0.287 | -1.198 | 0.231 | -0.908 | 0.219 |
educ | 0.0537 | 0.016 | 3.340 | 0.001 | 0.022 | 0.085 |
age | 0.0053 | 0.003 | 1.790 | 0.073 | -0.001 | 0.011 |
couple | -0.3391 | 0.097 | -3.489 | 0.000 | -0.530 | -0.149 |
child | 0.0397 | 0.032 | 1.256 | 0.209 | -0.022 | 0.102 |
Le résultat est le même que lors de l'utilisation du module probit de statsmodels. Il n'y a pas de module officiellement fusionné pour les modèles Tobit, mais si vous utilisez GenericLikelihoodModels, il semble que vous puissiez le créer simplement en augmentant la fonction de vraisemblance.
Bien qu'il s'agisse d'un modèle Heckit, statsmodels et linearmodels n'avaient pas de module capable d'effectuer l'estimation en deux étapes et l'estimation la plus probable en l'état, pour autant que j'ai lu le document. Je vous serais reconnaissant si vous pouviez me le faire savoir. Cependant, bien que pas officiellement fusionné, il y avait un module appelé [Heckman] dans la branche.
Utilisez ceci.
import Heckman
#Lecture et formatage des données
read_stata('piaac.dta')
df_3 = df[df['gender']== 'Female']
df_3 = df_3[['educ','couple','child','age']]
df_3 = df_3.dropna()
df_3['wage'] = df['wage']
df_3[['educ','age']] = df_3[['educ','age']].apply(pd.to_numeric)
df_3['experience'] = df_3['age']-df_3['educ']-6
df_3['experience_2'] = (df_3['experience']**2)/100
df_3['logwage'] = np.log(df_3['wage'])
#Confirmation des données
df_3
Certaines personnes n'ont pas respecté leur salaire pour une raison quelconque. Il est possible que vous ne travailliez pas en premier lieu parce que le salaire offert est inférieur au salaire réservé. Si les salaires sont renvoyés aux variables explicatives telles quelles, la sélection de l'échantillon risque de devenir un problème.
Quoi qu'il en soit, afin de reproduire le tableau, je vais exécuter OLS tel quel.
#Estimation OLS
result_5_1 = ols(formula = 'logwage ~ educ + experience + experience_2',
data = df_3).fit(cov_type='HC1',use_t=True)
#Vérifiez le résultat
result_5_1.summary()
coef | stderr | t | P>t | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | 5.8310 | 0.236 | 24.726 | 0.000 | 5.368 | 6.294 |
educ | 0.0862 | 0.014 | 6.074 | 0.000 | 0.058 | 0.114 |
experience | 0.0069 | 0.009 | 0.762 | 0.446 | -0.011 | 0.025 |
experience_2 | -0.0126 | 0.015 | -0.820 | 0.413 | -0.043 | 0.018 |
No. Observations: | 984 |
---|
Il y avait 1747 échantillons au total, mais le nombre d'échantillons utilisés est de 984.
#Créez un vecteur de variables expliquées.
endog = df_3['logwage']
#Créez une matrice de variables explicatives pour la formule de sélection.
exog_select = df_3[['educ','experience','experience_2','couple','child']]
exog_select = sm.add_constant(exog_select,prepend=True)
#Créez une matrice de variables explicatives pour l'équation de deuxième étape.
exog = df_3[['educ','experience','experience_2']]
exog = sm.add_constant(exog,prepend=True)
#Estimation en deux étapes de Heckman
result_5_2 = Heckman.Heckman(endog,exog,exog_select).fit(method='twostep')
#Vérifiez le résultat
result_5_2.summary()
#Estimation la plus probable
result_5_4 = Heckman.Heckman(endog,exog,exog_select).fit(method='mle',
method_mle='nm',
maxiter_mle=2000)
#Vérifiez le résultat
result_5_4.summary()
En préparant cette réponse, je me suis référé aux matériaux suivants.
Burce E.Hansen(2020)"ECONOMETRICS"
Recommended Posts