Bon! J’aurais peut-être dû commencer par là. Les données de panel présentent une structure particulière. La répétition des observations dans le temps permet d’appréhender à la fois des différences entre individus et entre périodes, mais aussi des différences pour un même individu observé à différents point du temps ou pour un point du temps donné des différences entre individus… Cela se concrétise par des tendances au niveau de données, plus précisément au niveau de la variation de leur valeurs. C’est autour de l’appréhension de cette variabilité que ce court billet s’organise.
library(tidyverse)
library(plm)
library(panelr)
Rechargeons le jeu de données.
wages<-WageData
Revenons sur nos données de base et intéressons-nous à la variabilité de notre variable expliquée (lwage). Cette variabilité est généralement exprimée par sa variance (\(s^2\)) ou son écart type (\(s\)) (construit à partir de la somme des écarts carrés à la moyenne - sec par la suite). Recalculons-les.
wages %>% select(lwage) %>%
summarise_all(c(var,sd,function(x){var(x)*(n()-1)})) %>%
round(digits=5) %>%
rename(variance=fn1,ecart_type=fn2,somme_écarts_carrés_sec=fn3)
## variance ecart_type somme_écarts_carrés_sec
## 1 0.21299 0.46151 886.9049
Dans le cadre de données de panel, ces indicateurs sont qualifiés de globaux (Overall). La variance (échantillon) globale correspond à la variance classique.
\[s^2=\frac{1}{N.T-1}\sum^{N}_{i=1}\sum^{T}_{t=1}(y_{it}-\bar{y})^2=\frac{1}{N.T-1}.sec\]
où N est le nombre total d’individus et T le nombre de périodes sur lesquels ils sont observés.
Les dimensions individuelles et temporelles des données permettent de décomposer cette variabilité pour mieux la comprendre. A ce niveau, il y plusieurs possibilités.
Between individual et Within individual
La plus courante consiste à distinguer la variabilité associée aux différences entre individus (Between individuals) indépendamment du temps (=> la variabilité inter-individuelle) et la variabilité associée à l’évolution de chaque individu dans le temps (Within individuals) indépendamment de leurs caractéristiques invariables (=> la variabilité intra-individuelle). Ces deux sources de variabilité se cumulent pour former la variabilité globale. On a ainsi:
\[ sec= sec_{B_i} + sec_{W_i} \]
La variabilité inter-individuelle (\(sec_{B_i}\)) se mesure par la somme des écarts carrés des moyennes individuelles calculées sur l’ensemble des périodes à la moyenne globale.
\[ sec_{B_i}=T\sum^{N}_{i=1}(\bar{y_{i}}-\bar{y})^2\]
Calculons cette variabilité inter-individuelle à partir de nos données.
moy_lwage<-mean(wages$lwage)
sec_Bi<-wages %>% select(lwage,id) %>% group_by(id) %>%
summarise(moy_id=mean(lwage),es_id=(moy_id-moy_lwage)^2)%>%
ungroup() %>%
summarize(secbi=sum(es_id)*length(unique(wages$t))) %>%
unlist() %>% unname()
sec_Bi
## [1] 646.2537
On retrouve souvent cette valeur présentée sous forme de la variance inter-individuelle (Between variance ou Between individual variance). Elle est juste normée par le nombre d’individus moins 1 (puisque l’on est sur une variance échantillon).
\[ s^2_{B_i}=\frac{1}{N-1}\sum^{N}_{i=1}(\bar{y_{i}}-\bar{y})^2=\frac{1}{N-1}.sec_{B_i} \]
Calculons la.
var_bi<-sec_Bi/(length(unique(wages$id))-1)
var_bi
## [1] 1.087969
La variabilité intra-individuelle (\(sec_{W_i}\)) se mesure par la somme des écarts carrés des valeurs individuelles aux moyennes individuelles sur l’ensemble de la période.
\[ sec_{W_i}=\sum^{N}_{i=1}\sum^{T}_{t=1}(y_{it}-\bar{y_i})^2 \]
Voyons ce que cela donne sur nos données.
sec_Wi<-wages %>% group_by(id) %>%
mutate(moy_id=mean(lwage),ec2=(lwage-moy_id)^2) %>%
ungroup() %>% summarize(secbi=sum(ec2)) %>%
unlist() %>% unname()
sec_Wi
## [1] 240.6512
En additionnant cette variabilité intra-individuelle (\(sec_{W_i}\)) et la variabilité inter-individuelle (\(sec_{B_i}\)), on retrouve bien la variabilité globale (\(sec\)).
sec_Bi+sec_Wi
## [1] 886.9049
La variabilité intra-individuelle est généralement présentée sous la forme de la variance intra-individuelle (Within variance ou Within individual variable).
\[ s^2_{W_i}=\frac{1}{N.T-1}\sum^{N}_{i=1}\sum^{T}_{t=1}(y_{it}-\bar{y_i})^2 \]
Sa valeur sur nos données est la suivante:
var_wi<-sec_Wi/(nrow(wages)-1)
var_wi
## [1] 0.05779328
La somme des variances between et within doit être ajusté pour correspondre à la variance totale.
(var_bi*(length(unique(wages$id))-1))/(nrow(wages)-1)+var_wi
## [1] 0.2129935
Between time et Within time
Une autre manière d’appréhender (moins usitée) la variabilité de nos données consiste à organiser la décomposition non plus sur les individus mais sur les périodes. On a ainsi la variabilité globale qui se décompose en variabilité inter-temportelle (between time) et variabilité intra-temporelle (within time).
\[ sec= sec_{B_t} + sec_{W_t} \]
La variabilité inter-temporelle (\(sec_{B_t}\)) se mesure par la somme des écarts carrés des moyennes sur les périodes calculées sur l’ensemble des individus à la moyenne globale.
\[sec_{B_t}=N.\sum^{T}_{i=1}(\bar{y_{t}}-\bar{y})^2 \]
Calculons la.
sec_Bt<-wages %>% select(lwage,t) %>% group_by(t) %>%
summarise(moy_t=mean(lwage),es_t=(moy_t-moy_lwage)^2)%>%
ungroup() %>%
summarize(secbi=sum(es_t)*length(unique(wages$id))) %>%
unlist() %>% unname()
sec_Bt
## [1] 157.4736
Cette valeur peut être présentée sous forme de la variance inter-temporelle (Between variance ou Between time variance). Elle est juste normée par le nombre de périodes moins une (puisque l’on est sur une variance échantillon).
\[s^2_{B_t}=\frac{1}{T-1}\sum^{T}_{i=1}(\bar{y_{t}}-\bar{y})^2=\frac{1}{T-1}.sec_{B_t} \]
Sa valeur sur nos données est la suivante:
var_bt<-sec_Bt/(length(unique(wages$t))-1)
var_bt
## [1] 26.24561
La variabilité intra-temporelle (\(sec_{W_t}\)) se mesure par la somme des écarts carrés des valeurs aux moyennes périodiques sur l’ensemble des individus.
\[ sec_{W_t}=\sum^{N}_{i=1}\sum^{T}_{t=1}(y_{it}-\bar{y_t})^2 \]
Voyons ce que cela donne.
sec_Wt<-wages %>% group_by(t) %>%
mutate(moy_t=mean(lwage),ec2=(lwage-moy_t)^2) %>%
ungroup() %>% summarize(secbt=sum(ec2)) %>%
unlist() %>% unname()
sec_Wt
## [1] 729.4313
En additionnant cette variabilité intra-temporelle (\(sec_{W_t}\)) et la variabilité inter-temporelle (\(sec_{B_t}\)), on retrouve bien la variabilité globale (\(sec\)).
sec_Bt+sec_Wt
## [1] 886.9049
Encore une fois, la variabilité intra-temporelle est plus généralement présentée via la variance associée dont l’expression est la suivante:
\[s^2_{W_t}=\frac{1}{N.T-1}\sum^{N}_{i=1}\sum^{T}_{t=1}(y_{it}-\bar{y_t})^2=\frac{1}{N.T-1}.sec_{W_t}\]
Sa valeur sur nos données est :
var_wt<-sec_Wt/(nrow((wages)-1))
var_wt
## [1] 0.1751336
La variance globale peut être retrouvée en ajustant la somme des variances between time et within time.
(var_bt*(length(unique(wages$t))-1))/(nrow((wages)-1))+var_wt
## [1] 0.2129424
Calucler l’ensemble rapidement
Le package plm fournit quelques éléments permettant de déterminer rapidement l’importance des variabilités individuelles et temporelles (within et between). Pour y accéder, il faut au préalable déclarer la structure de données au travers de la fonction pdata.frame(). Celles-ci prendront alors la forme d’une data frame spécifique au panel (des attributs indiquant les indexations des individus et des périodes). Créons dat_pan en l’utilisant et demandons l’affichage de ses attributs.
dat_pan <- pdata.frame(wages,index=c('id','t'))
str(attr(dat_pan,"index"))
## Classes 'pindex' and 'data.frame': 4165 obs. of 2 variables:
## $ id: Factor w/ 595 levels "1","2","3","4",..: 1 1 1 1 1 1 1 2 2 2 ...
## $ t : Factor w/ 7 levels "1","2","3","4",..: 1 2 3 4 5 6 7 1 2 3 ...
Pour avoir une idée de la décomposition sommaire de la variabilité de notre variable explicative, il suffit d’appeler la fonction summary().
summary(dat_pan$lwage)
## total sum of squares: 886.9049
## id time
## 0.7286618 0.1775542
##
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.605 6.395 6.685 6.676 6.953 8.537
En plus d’une série de statistiques descriptives classiques, on nous donne la variabilité globale (somme des carrés des écarts) ainsi qu’une décomposition id time correspondant à la part de la variabilité between de ces dimensions dans la variabilité totale.
summary(dat_pan$lwage)[1:3]
## total between_id between_time
## 886.9049 646.2537 157.4736
c(summary(dat_pan$lwage)[2]/summary(dat_pan$lwage)[1],
summary(dat_pan$lwage)[3]/summary(dat_pan$lwage)[1])
## between_id between_time
## 0.7286618 0.1775542
On voit bien ici que la variabilité entre individus indépendamment de la période (73% de variabilité totale) est plus importante que celles entre périodes indépendamment des caractéristiques propres (invariables) des individus (18%).
L’ensemble peut être avec un peu de travail étendue et synthétisée dans un tableau unique. Commençons par créer des fonctions nous permettant de sortir les variations within et between.
sec_W<-function(dat,x,type="id"){
attach(dat,warn.conflicts = FALSE)
if(type=="t"){
sec_wt<-sum(tapply(x,t,var)*(length(unique(id))-1))
names(sec_wt)<-"sec_wt"
detach(dat)
return(sec_wt)}
if(type=="id") {
sec_wi<-sum(tapply(x,id,var)*(length(unique(t))-1))
names(sec_wi)<-"sec_wi"
detach(dat)
return(sec_wi)}
}
sec_B<-function(dat,x,type="id"){
attach(dat,warn.conflicts = FALSE)
if(type=="t"){
sec_Bt<-sum((tapply(x,t, mean)-mean(x))^2)*length(unique(id))
names(sec_Bt)<-"sec_Bt"
return(sec_Bt)}
if(type=="id") {
sec_Bi<-sum((tapply(x,id, mean)-mean(x))^2)*length(unique(t))
names(sec_Bi)<-"sec_Bi"
return(sec_Bi)}
}
Assemblons l’ensemble dans un tableau en ajoutant la variation globale et la répartition de cette dernière en pourcentages en fonction de nos types de variabilité.
tab_sec<-function(dat,x){
attach(dat,warn.conflicts = FALSE)
sec_g<-var(x)*4164
detach(dat)
d1<-data.frame(
id_=c(sec_W(dat,x,type="id"),sec_B(dat,x,type="id"),sec=sec_g),
time_=c(sec_W(wages,x,type="t"),sec_B(dat,x,type="t"),sec=sec_g))
dp<-round(d1/sec_g*100,digits=2)
colnames(dp)<-c("prct_id","prct_time")
tab<-cbind(d1,dp)
row.names(tab)<-c('sec within','sec between','sec')
tab
}
tab_sec(wages,lwage)
## id_ time_ prct_id prct_time
## sec within 240.6512 729.4313 27.13 82.24
## sec between 646.2537 157.4736 72.87 17.76
## sec 886.9049 886.9049 100.00 100.00
L’analyse peut être appliquée à notre variable explicative (wks).
tab_sec(wages,wks)
## id_ time_ prct_id prct_time
## sec within 64702.00 109138.7496 59.06 99.63
## sec between 44843.05 406.2972 40.94 0.37
## sec 109545.05 109545.0468 100.00 100.00