** Apprenez en 10 minutes APPEL PY **
Cet article est une traduction japonaise de ce cahier.
import pandas as pd
import numpy as np
import statsmodels.api as sm # for datasets
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
** Présentation des fonctionnalités d'Appelpy. ** **
--L'analyse exploratoire des données --Estimation du modèle --Diagnostic de modèle
Remarque: ce notebook a été exécuté avec la dernière version d'Appelpy v0.4.2 et ses dépendances.
Explorons maintenant les fonctionnalités d'Appelpy en utilisant l'un des ensembles de données les plus riches en économie métrique. The California Test Score Data Set (** Caschool **).
Chargez l'ensemble de données avec Pandas et récupérez les données avec la méthode Statsmodels.
# Load data
df = sm.datasets.get_rdataset('Caschool', 'Ecdat').data
# Add together the two test scores (total score)
df['scrtot'] = df['readscr'] + df['mathscr']
df.head()
distcod | county | district | grspan | enrltot | teachers | calwpct | mealpct | computer | testscr | compstu | expnstu | str | avginc | elpct | readscr | mathscr | scrtot | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 75119 | Alameda | Sunol Glen Unified | KK-08 | 195 | 10.900000 | 0.510200 | 2.040800 | 67 | 690.799988 | 0.343590 | 6384.911133 | 17.889910 | 22.690001 | 0.000000 | 691.599976 | 690.000000 | 1381.599976 |
1 | 61499 | Butte | Manzanita Elementary | KK-08 | 240 | 11.150000 | 15.416700 | 47.916698 | 101 | 661.200012 | 0.420833 | 5099.380859 | 21.524664 | 9.824000 | 4.583333 | 660.500000 | 661.900024 | 1322.400024 |
2 | 61549 | Butte | Thermalito Union Elementary | KK-08 | 1550 | 82.900002 | 55.032299 | 76.322601 | 169 | 643.599976 | 0.109032 | 5501.954590 | 18.697226 | 8.978000 | 30.000002 | 636.299988 | 650.900024 | 1287.200012 |
3 | 61457 | Butte | Golden Feather Union Elementary | KK-08 | 243 | 14.000000 | 36.475399 | 77.049202 | 85 | 647.700012 | 0.349794 | 7101.831055 | 17.357143 | 8.978000 | 0.000000 | 651.900024 | 643.500000 | 1295.400024 |
4 | 61523 | Butte | Palermo Union Elementary | KK-08 | 1335 | 71.500000 | 33.108601 | 78.427002 | 171 | 640.849976 | 0.128090 | 5235.987793 | 18.671329 | 9.080333 | 13.857677 | 641.799988 | 639.900024 | 1281.700012 |
Maintenant que nous avons les données, examinons de plus près la distribution de certaines variables clés avant la modélisation.
Appelpy a un module ** ʻeda` ** (analyse exploratoire des données).
from appelpy.eda import statistical_moments
Obtenez tous les moments statistiques à la fois.
statistical_moments(df)
mean | var | skew | kurtosis | |
---|---|---|---|---|
distcod | 67472.8 | 1.20201e+07 | -0.0307844 | -1.09626 |
enrltot | 2628.79 | 1.53124e+07 | 2.87017 | 10.2004 |
teachers | 129.067 | 35311.2 | 2.93254 | 11.219 |
calwpct | 13.246 | 131.213 | 1.68306 | 4.58959 |
mealpct | 44.7052 | 735.678 | 0.183954 | -0.999802 |
computer | 303.383 | 194782 | 2.87169 | 10.7729 |
testscr | 654.157 | 363.03 | 0.0916151 | -0.254288 |
compstu | 0.135927 | 0.00421926 | 0.922369 | 1.43113 |
expnstu | 5312.41 | 401876 | 1.0679 | 1.87571 |
str | 19.6404 | 3.57895 | -0.0253655 | 0.609597 |
avginc | 15.3166 | 52.2135 | 2.21516 | 6.53212 |
elpct | 15.7682 | 334.375 | 1.4268 | 1.4354 |
readscr | 654.97 | 404.331 | -0.0583962 | -0.358049 |
mathscr | 653.343 | 351.72 | 0.255082 | -0.159811 |
scrtot | 1308.31 | 1452.12 | 0.0916149 | -0.254288 |
Au cœur d'Appelpy se trouve la modélisation de ce qui se passe dans l'ensemble de données.
Le module ** linear_model
** contient des classes pour la modélisation des données. Exemple: OLS (moindres carrés ordinaires)
from appelpy.linear_model import OLS
** Voici une recette pour estimer un modèle linéaire. ** **
y_list
et X_list
, pour la variable dépendante (y) et la variable indépendante (X).y_list = ['scrtot']
X_list = ['avginc', 'str', 'enrltot', 'expnstu']
model_nonrobust = OLS(df, y_list, X_list).fit()
model_selection_stats
, y compris l'erreur de racine carrée moyenne carrée (Root MSE).model_nonrobust.model_selection_stats
{'root_mse': 25.85923055850994,
'r_squared': 0.5438972040191434,
'r_squared_adj': 0.5395010324916171,
'aic': 3929.1191674301117,
'bic': 3949.320440986499}
Obtenez un résumé des Statsmodels avec l'attribut results_output
...
model_nonrobust.results_output
Dep. Variable: | scrtot | R-squared: | 0.544 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.540 |
Method: | Least Squares | F-statistic: | 123.7 |
Date: | Mon, 04 May 2020 | Prob (F-statistic): | 2.05e-69 |
Time: | 18:32:26 | Log-Likelihood: | -1959.6 |
No. Observations: | 420 | AIC: | 3929. |
Df Residuals: | 415 | BIC: | 3949. |
Df Model: | 4 | ||
Covariance Type: | nonrobust |
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
const | 1312.9203 | 27.833 | 47.171 | 0.000 | 1258.208 | 1367.632 |
avginc | 3.8640 | 0.185 | 20.876 | 0.000 | 3.500 | 4.228 |
str | -1.3954 | 0.893 | -1.563 | 0.119 | -3.150 | 0.359 |
enrltot | -0.0016 | 0.000 | -4.722 | 0.000 | -0.002 | -0.001 |
expnstu | -0.0061 | 0.003 | -2.316 | 0.021 | -0.011 | -0.001 |
Omnibus: | 7.321 | Durbin-Watson: | 0.763 |
---|---|---|---|
Prob(Omnibus): | 0.026 | Jarque-Bera (JB): | 7.438 |
Skew: | -0.326 | Prob(JB): | 0.0243 |
Kurtosis: | 2.969 | Cond. No. | 1.39e+05 |
... Maintenant, il est enfin facile d'obtenir les résultats d'un modèle standardisé en utilisant l'attribut results_output_standardized
.
model_nonrobust.results_output_standardized
# This is a Styler object; add .data to access the underlying Pandas dataframe
coef | t | P>|t| | coef_stdX | coef_stdXy | stdev_X | |
---|---|---|---|---|---|---|
scrtot | ||||||
avginc | +3.8640 | +20.876 | 0.000 | +27.9209 | +0.7327 | 7.2259 |
str | -1.3954 | -1.563 | 0.119 | -2.6399 | -0.0693 | 1.8918 |
enrltot | -0.0016 | -4.722 | 0.000 | -6.3035 | -0.1654 | 3913.1050 |
expnstu | -0.0061 | -2.316 | 0.021 | -3.8364 | -0.1007 | 633.9371 |
La sortie est similaire à la commande listcoef
de Stata.
Appelez la méthode diagnostic_plot
de l'objet modèle pour afficher de nombreux diagnostics de régression visuels **: **.
--pp_plot
: tracé P-P
-- qq_plot
: tracé Q-Q
--rvp_plot
: tracé des valeurs résiduelles et prédites
--rvf_plot
: tracé des valeurs résiduelles et mesurées
Le module ** diagnostics
** d'Appelpy a une suite de classes et de fonctions pour le diagnostic de régression.
Si les diagnostics visuels ne suffisent pas, appelez d'autres méthodes comme heteroskedasticity_test
pour faire un test formel.
Y a-t-il des observations qui polluent le modèle? Passez l'objet modèle à la classe BadApples
pour voir les points d'influence, les valeurs aberrantes et l'effet de levier élevé.
** Voici une recette pour un ensemble 2x2 de tracés de diagnostic. ** **
fig, axarr = plt.subplots(2, 2, figsize=(10, 10))
model_nonrobust.diagnostic_plot('pp_plot', ax=axarr[0][0])
model_nonrobust.diagnostic_plot('qq_plot', ax=axarr[1][0])
model_nonrobust.diagnostic_plot('rvf_plot', ax=axarr[1][1])
axarr[0, 1].axis('off')
plt.tight_layout()
Bon chagrin. Le modèle spécifié a un problème particulier avec des scores de test supérieurs à 1350.
Il semble y avoir une variance non constante dans le graphique RVF.
Il est probablement réparti uniformément, mais faisons un test plus spécifique.
from appelpy.diagnostics import heteroskedasticity_test
Appelez l'un des nombreux ** tests d'isodispersité **. Exemple:
hettest
)bptest
de R)bp_stats = heteroskedasticity_test('breusch_pagan', model_nonrobust)
print('Breusch-Pagan test :: {}'.format(bp_stats['distribution'] + '({})'.format(bp_stats['nu'])))
print('Test statistic: {:.4f}'.format(bp_stats['test_stat']))
print('Test p-value: {:.4f}'.format(bp_stats['p_value']))
Breusch-Pagan test :: chi2(1)
Test statistic: 2.5579
Test p-value: 0.1097
bps_stats = heteroskedasticity_test('breusch_pagan_studentized', model_nonrobust)
print('Breusch-Pagan test (studentized) :: {}'.format(bps_stats['distribution'] + '({})'.format(bps_stats['nu'])))
print('Test statistic: {:.4f}'.format(bps_stats['test_stat']))
print('Test p-value: {:.4f}'.format(bps_stats['p_value']))
Breusch-Pagan test (studentized) :: chi2(1)
Test statistic: 11.3877
Test p-value: 0.0225
Le test Studentized Breusch-Pagan est considéré comme plus robuste et montre des différences significatives par rapport à l'hypothèse d'hypodispersité initiale, donc adaptons-le à un modèle avec l'erreur standard Heteroskedastic-Robust (erreur HC1
). ..
model_hc1 = OLS(df, y_list, X_list, cov_type='HC1').fit()
model_hc1.results_output
Dep. Variable: | scrtot | R-squared: | 0.544 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.540 |
Method: | Least Squares | F-statistic: | 78.60 |
Date: | Mon, 04 May 2020 | Prob (F-statistic): | 1.36e-49 |
Time: | 18:32:27 | Log-Likelihood: | -1959.6 |
No. Observations: | 420 | AIC: | 3929. |
Df Residuals: | 415 | BIC: | 3949. |
Df Model: | 4 | ||
Covariance Type: | HC1 |
coef | std err | z | P>|z| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
const | 1312.9203 | 29.364 | 44.711 | 0.000 | 1255.367 | 1370.474 |
avginc | 3.8640 | 0.240 | 16.119 | 0.000 | 3.394 | 4.334 |
str | -1.3954 | 0.932 | -1.498 | 0.134 | -3.221 | 0.430 |
enrltot | -0.0016 | 0.000 | -5.794 | 0.000 | -0.002 | -0.001 |
expnstu | -0.0061 | 0.003 | -2.166 | 0.030 | -0.012 | -0.001 |
Omnibus: | 7.321 | Durbin-Watson: | 0.763 |
---|---|---|---|
Prob(Omnibus): | 0.026 | Jarque-Bera (JB): | 7.438 |
Skew: | -0.326 | Prob(JB): | 0.0243 |
Kurtosis: | 2.969 | Cond. No. | 1.39e+05 |
Quels sont les retributeurs importants (variables indépendantes) actuellement?
model_hc1.significant_regressors(0.05)
['avginc', 'enrltot', 'expnstu']
Les retours de «str» (ratio élèves-enseignant) et «expnstu» sont particulièrement pertinents pour investir dans les étudiants. Vous pouvez faire un ** test Wald ** pour tester si les deux rétributeurs sont ensemble et significativement différents de 0.
from appelpy.diagnostics import wald_test
wald_stats = wald_test(model_hc1, ['str', 'expnstu'])
print('Wald test :: {}'.format(wald_stats['distribution'] + '({})'.format(wald_stats['nu'])))
print('Test statistic: {:.4f}'.format(wald_stats['test_stat']))
print('Test p-value: {:.4f}'.format(wald_stats['p_value']))
Wald test :: chi2(2)
Test statistic: 4.7352
Test p-value: 0.0937
Sans surprise, l'erreur standard de certaines variables est plus élevée avec l'erreur HC1 qu'avec l'erreur non robuste.
pd.concat([pd.Series(model_nonrobust.results.bse, name='std_error_nonrobust'),
pd.Series(model_hc1.results.bse, name='std_error_hc1')], axis='columns')
std_error_nonrobust | std_error_hc1 | |
---|---|---|
const | 27.833430 | 29.364467 |
avginc | 0.185093 | 0.239715 |
str | 0.892703 | 0.931541 |
enrltot | 0.000341 | 0.000278 |
expnstu | 0.002613 | 0.002794 |
Inspectons les résultats observés.
--Haute influence --Effet de levier élevé --Plus
from appelpy.diagnostics import BadApples
Configurez une instance de BadApples
à l'aide d'un objet modèle.
bad_apples = BadApples(model_hc1).fit()
Tracons la valeur de levier par rapport au carré du résidu normalisé.
Les observations dans le quadrant supérieur droit ont un effet de levier et des valeurs résiduelles supérieurs à la moyenne (c'est-à-dire les observations les plus influentes du modèle).
fig, ax = plt.subplots(figsize=(11,7))
bad_apples.plot_leverage_vs_residuals_squared(annotate=True)
plt.show()
La valeur de l'effet de levier est stockée dans l'attribut mesures_leverage
.
bad_apples.measures_leverage.sort_values(ascending=False).head()
48 0.113247
34 0.085633
404 0.076762
413 0.065741
159 0.061353
Name: leverage, dtype: float64
Jetons un coup d'œil aux cinq observations les plus exploitées.
bad_apples.show_extreme_observations().loc[[48,34,404,413,159]]
scrtot | avginc | str | enrltot | expnstu | |
---|---|---|---|---|---|
48 | 1261.099976 | 12.109128 | 19.017494 | 27176 | 5864.366211 |
34 | 1252.200012 | 11.722225 | 21.194069 | 25151 | 5117.039551 |
404 | 1387.900024 | 55.327999 | 16.262285 | 1059 | 6460.657227 |
413 | 1398.200012 | 50.676998 | 15.407042 | 687 | 7217.263184 |
159 | 1294.500000 | 14.298300 | 20.291372 | 21338 | 5123.474121 |
model_hc1.X_standardized.loc[[48,34,404,413,159]]
avginc | str | enrltot | expnstu | |
---|---|---|---|---|
48 | -0.443884 | -0.329278 | 6.273077 | 0.870684 |
34 | -0.497428 | 0.821246 | 5.755585 | -0.308182 |
404 | 5.537230 | -1.785664 | -0.401163 | 1.811299 |
413 | 4.893572 | -2.237740 | -0.496228 | 3.004803 |
159 | -0.140922 | 0.344087 | 4.781167 | -0.298032 |
Ces points à fort effet de levier ont des valeurs où au moins une variable indépendante est à au moins 4 écarts-types de la moyenne.
L'objet BadApples calcule une heuristique pour déterminer si la valeur d'échelle est "extrême".
Les index extrêmes sont stockés dans des attributs, par exemple les valeurs aberrantes sont stockées dans ʻindices_outliers`.
bad_apples.indices_outliers
[5, 6, 7, 8, 9, 10, 13, 14, 37, 38, 47, 134, 370, 392, 403, 404, 415, 417]
Heuristique des valeurs aberrantes: si la valeur absolue des résidus standardisés ou la valeur absolue des résidus étudiés est supérieure à 2, la valeur observée est une valeur aberrante.
print(f"Proportion of observations as outliers: {len(bad_apples.indices_outliers) / len(df):.4%}")
Proportion of observations as outliers: 4.2857%
En raison de son heuristique, moins d'environ 5% des valeurs observées devraient être considérées comme des valeurs aberrantes.
Considérez également diverses mesures d'influence telles que la distance de cuisson, les dffits et le dfbeta.
bad_apples.measures_influence.sort_values('cooks_d', ascending=False).head()
dfbeta_const | dfbeta_avginc | dfbeta_str | dfbeta_enrltot | dfbeta_expnstu | cooks_d | dffits_internal | dffits | |
---|---|---|---|---|---|---|---|---|
404 | 0.010742 | -0.811324 | 0.068295 | 0.061925 | 0.039761 | 0.152768 | -0.873981 | -0.882753 |
403 | 0.024082 | -0.529623 | 0.016131 | 0.031978 | 0.026944 | 0.063718 | -0.564440 | -0.567338 |
413 | 0.074297 | -0.373064 | 0.013021 | 0.033955 | -0.099557 | 0.044116 | -0.469661 | -0.470876 |
38 | -0.277356 | -0.193382 | 0.217223 | -0.136237 | 0.315817 | 0.030955 | -0.393412 | -0.397701 |
415 | -0.157629 | 0.099707 | 0.045684 | -0.026836 | 0.249169 | 0.025414 | 0.356468 | 0.357936 |
--Chargez l'ensemble de données et prétraitez-le avec Pandas.
--Appelpy ** ʻeda**: Inspectez l'ensemble de données du modèle avec des fonctions utiles telles que les moments statistiques. --Appelpy ** modélisation **.
Linear_modelcontient des classes telles que OLS et WLS pour l'estimation du modèle. Utilisez une courte recette pour chaque modèle pour accéder aux estimations du modèle. --Appelpy **
diagnostics **: vérifie si les estimations du modèle sont valides avec des graphiques de diagnostic, des tests statistiques et des diagnostics tels que
BadApples` pour l'analyse d'impact.
--Régression logistique (sous discrete_model
)