comparaison de groupes dans des modèles FE à mesures répétées, avec une composante d'erreur imbriquée, estimée à l'aide de plm

8

J'ai estimé des modèles à effets fixes de mesures répétées, avec une composante d'erreur imbriquée, en me basant sur des variables de regroupement, c'est-à-dire des modèles non imbriqués, en utilisant . Je suis maintenant intéressé à

  1. tester si les modèles complets sont significativement différents, c'est-à-dire où est le modèle complet pour et est le modèle complet pour et
    Ho:βFemale=βMale
    βFemaleFemalesβMaleMales
  2. tester ensuite les coefficients de régression sélectionnés entre deux groupes, c'est-à-dire où est le coefficient de régression pour les femmes at , et est le coefficient de régression pour les hommes à .
    Ho:βFemale==year1.5=βMale==year1.5
    βFemale==year1.5year1.5βMale==year1.5year1.5

Je vais illustrer la situation en utilisant l'exemple de travail ci-dessous,

Tout d'abord, certains packages nécessaires,

# install.packages(c("plm","texreg","tidyverse","lmtest"), dependencies = TRUE)
library(plm); library(lmtest); require(tidyverse)

Deuxièmement, une certaine préparation des données,

data(egsingle, package = "mlmRev")
dta <-  egsingle %>% mutate(Female = recode(female,.default = 0L,`Female` = 1L))

Troisièmement, j'estime un ensemble de modèles pour chaque sexe dans les données

MoSpc <- as.formula(math ~ Female + size + year)
dfMo = dta %>% group_by(female) %>%
    do(fitMo = plm(update(MoSpc, . ~ . -Female), 
       data = ., index = c("childid", "year", "schoolid"), model="within") )

Quatrièmement, regardons les deux modèles estimés,

texreg::screenreg(dfMo[[2]], custom.model.names = paste0('FE: ', dfMo[[1]]))
#> ===================================
#>            FE: Female   FE: Male   
#> -----------------------------------
#> year-1.5      0.79 ***     0.88 ***
#>              (0.07)       (0.10)   
#> year-0.5      1.80 ***     1.88 ***
#>              (0.07)       (0.10)   
#> year0.5       2.51 ***     2.56 ***
#>              (0.08)       (0.10)   
#> year1.5       3.04 ***     3.17 ***
#>              (0.08)       (0.10)   
#> year2.5       3.84 ***     3.98 ***
#>              (0.08)       (0.10)   
#> -----------------------------------
#> R^2           0.77         0.79    
#> Adj. R^2      0.70         0.72    
#> Num. obs.  3545         3685       
#> ===================================
#> *** p < 0.001, ** p < 0.01, * p < 0.05    #> 

Maintenant, je veux tester si ces deux modèles (OLS linéaire) sont significativement différents, cf. point1 ci-dessus. J'ai regardé SO et Internet et certains suggèrent que je dois utiliser plm::pFtest(), également suggéré ici , que j'ai essayé, mais je ne suis pas convaincu. J'aurais imaginé un test pour des modèles non imbriqués, un test de Cox possible lmtest::coxtest, mais je ne suis pas sûr du tout. Si quelqu'un ici pouvait peut-être m'aider.

J'ai essayé,

plm::pFtest(dfMo[[1,2]], dfMo[[2,2]])
# >
# > F test for individual effects
# >
# >data:  update(MoSpc, . ~ . - Female)
# >F = -0.30494, df1 = 113, df2 = 2693, p-value = 1
# >alternative hypothesis: significant effects

et,

lmtest::coxtest(dfMo[[1,2]], dfMo[[2,2]])
# > Cox test
# > 
# > Model 1: math ~ size + year
# > Model 2: math ~ size + year
# >                 Estimate Std. Error    z value Pr(>|z|)    
# > fitted(M1) ~ M2     0.32    1.66695     0.1898   0.8494    
# > fitted(M2) ~ M1 -1222.87    0.13616 -8981.1963   <2e-16 ***
# > ---
# > Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# > Warning messages:
# > 1: In lmtest::coxtest(dfMo[[1, 2]], dfMo[[2, 2]]) :
# >   models fitted on different subsets
# > 2: In lmtest::coxtest(dfMo[[1, 2]], dfMo[[2, 2]]) :
# >   different dependent variables specified

Deuxièmement, je suis intéressé à comparer les coefficients de régression entre deux groupes. Dites, est-ce que l'estimation year1.5de 3,04 est significativement différente de 3,17? Cf. point 2 ci-dessus.

Veuillez demander si l'un des éléments ci-dessus n'est pas clair et je me ferai un plaisir de vous en dire plus. Toute aide sera fortement appréciée!

Je me rends compte que cette question ressemble un peu à la programmation, mais je l'ai d'abord publiée dans SO. Cependant, DWin a eu la gentillesse de souligner que la question appartenait à CrossValidated et l'a migrée ici.

Eric Fail
la source
@DWin, merci. Je l'ai posté dans SO car j'ai déjà obtenu de très bonnes réponses concernant ce type de modèles et le plmpackage sur stackoverflow.com. Je prendrai plus de soin à l'avenir pour poster mes questions à l'endroit approprié. Merci.
Eric Fail
2
Ne pensez pas que le test F fonctionnerait ici, car vos deux modèles actuels (féminin et masculin) ne sont pas imbriqués. Pourquoi ne pas inclure run plm avec des termes d'interaction entre les variables féminines et explicatives, par exemple plm(math ~ Female * (x1 + x2)). Pour tester la première hypothèse nulle, vous exécutez simplement test F pour tous les coefficients associés à Female:x1, Female:x2. Pour tester le second null, il vous suffit de tester le paramètre associé à Female:year1.5.
semibruin
1
Merci pour votre commentaire. Je suis d'accord avec le fait que le test F n'est pas approprié ici. J'apprécie votre suggestion, mais je dois la mettre en œuvre dans un contexte où la solution d'interaction pourrait ne pas être réalisable. Cependant, si vous avez le temps, je vous suggère de poster votre solution comme réponse. Cela inspirera peut-être d'autres personnes qui ont un problème similaire.
Eric Fail
1
J'ai récemment abordé ce problème également, mais je n'ai pas pu le résoudre dans R. J'ai alors utilisé Stata, où nous pouvons appliquer suestpour voir si deux modèles sont significativement différents. Il y a une suest()fonction dans un package pour R mais je doute que ce soit la même chose. Dans Stata, il suests'agit d'une "estimation apparemment sans rapport". Notez que suregc'est quelque peu différent. Je suis également intéressé par une solution R. J'espère que cela aiderait en quelque sorte.
jay.sf
1
@jaySf, merci pour votre contribution. Peut-être que nous devons migrer cette question vers stackoverflow.com pour comprendre comment cela se fait dans r . Je n'ai pas utilisé de stata depuis des années. Pourriez-vous indiquer une documentation? Merci.
Eric Fail

Réponses:

3

Le code suivant implémente la pratique de l'interaction entre le Femalemannequin et l'année. Le test F en bas teste votre nullβFemale=βMale. La statistique t de la plmsortie teste votre valeur nulleβFemale:year=1.5=βMale:year=1.5. En particulier, pour year=1.5, la valeur de p est de 0,32.

library(plm)  # Use plm
library(car)  # Use F-test in command linearHypothesis
library(tidyverse)
data(egsingle, package = 'mlmRev')
dta <- egsingle %>% mutate(Female = recode(female, .default = 0L, `Female` = 1L))
plm1 <- plm(math ~ Female * (year), data = dta, index = c('childid', 'year', 'schoolid'), model = 'within')

# Output from `summary(plm1)` --- I deleted a few lines to save space.
# Coefficients:
#                 Estimate Std. Error t-value Pr(>|t|)    
# year-1.5          0.8842     0.1008    8.77   <2e-16 ***
# year-0.5          1.8821     0.1007   18.70   <2e-16 ***
# year0.5           2.5626     0.1011   25.36   <2e-16 ***
# year1.5           3.1680     0.1016   31.18   <2e-16 ***
# year2.5           3.9841     0.1022   38.98   <2e-16 ***
# Female:year-1.5  -0.0918     0.1248   -0.74     0.46    
# Female:year-0.5  -0.0773     0.1246   -0.62     0.53    
# Female:year0.5   -0.0517     0.1255   -0.41     0.68    
# Female:year1.5   -0.1265     0.1265   -1.00     0.32    
# Female:year2.5   -0.1465     0.1275   -1.15     0.25    
# ---

xnames <- names(coef(plm1)) # a vector of all independent variables' names in 'plm1'
# Use 'grepl' to construct a vector of logic value that is TRUE if the variable
# name starts with 'Female:' at the beginning. This is generic, to pick up
# every variable that starts with 'year' at the beginning, just write
# 'grepl('^year+', xnames)'.
picked <- grepl('^Female:+', xnames)
linearHypothesis(plm1, xnames[picked])

# Hypothesis:
# Female:year - 1.5 = 0
# Female:year - 0.5 = 0
# Female:year0.5 = 0
# Female:year1.5 = 0
# Female:year2.5 = 0
# 
# Model 1: restricted model
# Model 2: math ~ Female * (year)
# 
#   Res.Df Df Chisq Pr(>Chisq)
# 1   5504                    
# 2   5499  5  6.15       0.29
semibruin
la source
Très intéressant. Je vais l'essayer sur mes données de production. Merci. Vous pouvez publier la même réponse ici stackoverflow.com/questions/28334298/… et obtenir la prime là aussi.
Eric Fail
Question rapide, pensez-vous qu'il est possible de réécrire le -c(1:5)bloc d'une manière qui rendrait le code plus générique? J'ai des vecteurs de taille changeantes qui entrent et sortent et une réponse plus générique serait également bénéfique pour les autres.
Eric Fail
@EricFail j'ai remplacé -c(1:5)par l'expression régulière. C'est plus générique maintenant. En général, vous souhaitez utiliser greplpour faire correspondre les modèles en présence d'un grand nombre de variables.
semibruin