Стандартна кластеризація помилок в R (вручну або в PLM)


33

Я намагаюся зрозуміти стандартну помилку "кластеризації" і як виконати в R (це тривіально в Stata). У RI були невдалі, використовуючи plmабо написання власної функції. Я буду використовувати diamondsдані з ggplot2пакету.

Я можу робити фіксовані ефекти з будь-якими фіктивними змінними

> library(plyr)
> library(ggplot2)
> library(lmtest)
> library(sandwich)
> # with dummies to create fixed effects
> fe.lsdv <- lm(price ~ carat + factor(cut) + 0, data = diamonds)
> ct.lsdv <- coeftest(fe.lsdv, vcov. = vcovHC)
> ct.lsdv

t test of coefficients:

                      Estimate Std. Error  t value  Pr(>|t|)    
carat                 7871.082     24.892  316.207 < 2.2e-16 ***
factor(cut)Fair      -3875.470     51.190  -75.707 < 2.2e-16 ***
factor(cut)Good      -2755.138     26.570 -103.692 < 2.2e-16 ***
factor(cut)Very Good -2365.334     20.548 -115.111 < 2.2e-16 ***
factor(cut)Premium   -2436.393     21.172 -115.075 < 2.2e-16 ***
factor(cut)Ideal     -2074.546     16.092 -128.920 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

або де-значення лівої та правої сторони (тут немає інваріантних регресорів) та виправлення ступенів свободи.

> # by demeaning with degrees of freedom correction
> diamonds <- ddply(diamonds, .(cut), transform, price.dm = price - mean(price), carat.dm = carat  .... [TRUNCATED] 
> fe.dm <- lm(price.dm ~ carat.dm + 0, data = diamonds)
> ct.dm <- coeftest(fe.dm, vcov. = vcovHC, df = nrow(diamonds) - 1 - 5)
> ct.dm

t test of coefficients:

         Estimate Std. Error t value  Pr(>|t|)    
carat.dm 7871.082     24.888  316.26 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

Я не можу повторити ці результати plm, тому що у мене немає індексу "часу" (тобто це насправді не панель, а просто кластери, які можуть мати загальну зміщення в своїх помилках).

> plm.temp <- plm(price ~ carat, data = diamonds, index = "cut")
duplicate couples (time-id)
Error in pdim.default(index[[1]], index[[2]]) : 

Я також спробував зашифрувати власну коваріаційну матрицю із кластеризованою стандартною помилкою, використовуючи пояснення Stata щодо їх clusterваріанта ( пояснено тут ), яке полягає у вирішенні де , si кількість кластерів, - залишкове для спостереження і - вектор рядків предикторів, включаючи постійну (це також відображається як рівняння (7.22) у даних перерізу та панелі Вулдріджа

V^cluster=(XX)1(j=1ncujuj)(XX)1
uj=cluster jeixinceiiтгодхi). Але наступний код дає дуже великі матриці коваріації. Це дуже великі значення, враховуючи малу кількість кластерів, які у мене є? Зважаючи на те, що я не можу plmзробити кластери за одним фактором, я не впевнений, як орієнтувати свій код.
> # with cluster robust se
> lm.temp <- lm(price ~ carat + factor(cut) + 0, data = diamonds)
> 
> # using the model that Stata uses
> stata.clustering <- function(x, clu, res) {
+     x <- as.matrix(x)
+     clu <- as.vector(clu)
+     res <- as.vector(res)
+     fac <- unique(clu)
+     num.fac <- length(fac)
+     num.reg <- ncol(x)
+     u <- matrix(NA, nrow = num.fac, ncol = num.reg)
+     meat <- matrix(NA, nrow = num.reg, ncol = num.reg)
+     
+     # outer terms (X'X)^-1
+     outer <- solve(t(x) %*% x)
+ 
+     # inner term sum_j u_j'u_j where u_j = sum_i e_i * x_i
+     for (i in seq(num.fac)) {
+         index.loop <- clu == fac[i]
+         res.loop <- res[index.loop]
+         x.loop <- x[clu == fac[i], ]
+         u[i, ] <- as.vector(colSums(res.loop * x.loop))
+     }
+     inner <- t(u) %*% u
+ 
+     # 
+     V <- outer %*% inner %*% outer
+     return(V)
+ }
> x.temp <- data.frame(const = 1, diamonds[, "carat"])
> summary(lm.temp)

Call:
lm(formula = price ~ carat + factor(cut) + 0, data = diamonds)

Residuals:
     Min       1Q   Median       3Q      Max 
-17540.7   -791.6    -37.6    522.1  12721.4 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
carat                 7871.08      13.98   563.0   <2e-16 ***
factor(cut)Fair      -3875.47      40.41   -95.9   <2e-16 ***
factor(cut)Good      -2755.14      24.63  -111.9   <2e-16 ***
factor(cut)Very Good -2365.33      17.78  -133.0   <2e-16 ***
factor(cut)Premium   -2436.39      17.92  -136.0   <2e-16 ***
factor(cut)Ideal     -2074.55      14.23  -145.8   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

Residual standard error: 1511 on 53934 degrees of freedom
Multiple R-squared: 0.9272, Adjusted R-squared: 0.9272 
F-statistic: 1.145e+05 on 6 and 53934 DF,  p-value: < 2.2e-16 

> stata.clustering(x = x.temp, clu = diamonds$cut, res = lm.temp$residuals)
                        const diamonds....carat..
const                11352.64           -14227.44
diamonds....carat.. -14227.44            17830.22

Чи можна це зробити в R? Це досить поширена методика в економетриці (в цій лекції є короткий підручник ), але я не можу це зрозуміти в Р. Дякую!


7
@ricardh, прокляття всіх економістів за те, що вони не перевіряють, чи термін, який вони хочуть використовувати, вже використовується в статистиці. Кластер в цьому контексті означає групу і абсолютно не пов'язаний з кластерним аналізом, тому rseek дав вам непов'язані результати. Отже я видалив кластерний тег. Для аналізу даних на панелі перевіряйте пакет PLM . Він має гарну віньєтку, тож ви можете знайти те, що хочете. Що стосується вашого питання, то незрозуміло, чого ви хочете. У групових стандартних помилках?
mpiktas

@ricardh, це дуже допоможе, якби ви могли посилатися на якийсь посібник із Stata, де clusterпояснюється ця опція. Я впевнений, що можна було б повторити в Р.
mpiktas

2
+1 для цього коментаря. економісти колонізують термінологію як божевільний. Хоча іноді важко вибрати лиходія. Ii пройшов деякий час, наприклад, поки я не зрозумів, factorщо не має нічого спільного, factanalале стосується категоризованих змінних. Однак кластер в R відноситься до кластерного аналізу, k-означає просто метод розподілу: statmethods.net/advstats/cluster.html . Я не розумію вашого питання, але я також здогадуюсь, що кластер не має нічого спільного з цим.
hans0l0

@mpiktas, @ ran2 - Дякую! Сподіваюся, я уточнив питання. Коротше кажучи, чому "стандартне кластеризація помилок" існує, якщо це лише фіксовані ефекти, які вже існували?
Річард Геррон

1
Функція cluster.vcov в пакеті "multiwayvcov" робить те, що ви шукаєте.

Відповіді:


29

Для білих стандартних помилок, згрупованих за групою, plmспробуйте фреймворк

coeftest(model.plm, vcov=vcovHC(model.plm,type="HC0",cluster="group"))

де model.plmє модель PLM.

Дивіться також це посилання

http://www.inside-r.org/packages/cran/plm/docs/vcovHC або документація на пакет PLM

Редагувати:

Для двостороннього кластеризації (наприклад, групи та часу) дивіться наступне посилання:

http://people.su.se/~ma/clustering.pdf

Ось ще одне корисне керівництво для пакета PLM, зокрема, що пояснює різні варіанти кластеризованих стандартних помилок:

http://www.princeton.edu/~otorres/Panel101R.pdf

Кластеризацію та іншу інформацію, особливо для Stata, можна знайти тут:

http://www.kellogg.northwestern.edu/facturing/petersen/htm/papers/se/se_programming.htm

EDIT 2:

Ось приклади, які порівнюють R та stata: http://www.richard-bluhm.com/clustered-ses-in-r-and-stata-2/

Також multiwayvcovможе бути корисною. Ця публікація надає корисний огляд: http://rforpublichealth.blogspot.dk/2014/10/easy-clustered-standard-errors-in-r.html

З документації:

library(multiwayvcov)
library(lmtest)
data(petersen)
m1 <- lm(y ~ x, data = petersen)

# Cluster by firm
vcov_firm <- cluster.vcov(m1, petersen$firmid)
coeftest(m1, vcov_firm)
# Cluster by year
vcov_year <- cluster.vcov(m1, petersen$year)
coeftest(m1, vcov_year)
# Cluster by year using a formula
vcov_year_formula <- cluster.vcov(m1, ~ year)
coeftest(m1, vcov_year_formula)

# Double cluster by firm and year
vcov_both <- cluster.vcov(m1, cbind(petersen$firmid, petersen$year))
coeftest(m1, vcov_both)
# Double cluster by firm and year using a formula
vcov_both_formula <- cluster.vcov(m1, ~ firmid + year)
coeftest(m1, vcov_both_formula)

для мене coeftest(model.plm, vcov=vcovHC(model.plm,type="HC0")) , а також coeftest(model.plm, vcov=vcovHC(model.plm,type="HC0",cluster="group"))дають однакові результати. Чи знаєте ви, чому це так?
Пітер Пан

1
Посилання people.su.se/~ma/clustering.pdf більше не працює. Ви пам’ятаєте заголовок сторінки?
MERose

8

Після багато прочитаного я знайшов рішення зробити кластеризацію в lmрамках.

Існує відмінна біла книга Махмуда Арая, яка пропонує підручник з кластеризації в lmрамках, який він робить з виправленнями ступенів свободи замість моїх брудних спроб, описаних вище. Він надає свої функції як для одно- і двосторонніх матриць ковариации кластеризації тут .

Нарешті, хоча вміст не доступний безкоштовно, в Angry and Pischke's Most Besmless Econometrics є розділ про кластеризацію, який був дуже корисним.


Оновіть 27.04.2015, щоб додати код із допису в блозі .

api=read.csv("api.csv") #create the variable api from the corresponding csv
attach(api) # attach of data.frame objects
api1=api[c(1:6,8:310),] # one missing entry in row nr. 7
modell.api=lm(API00 ~ GROWTH + EMER + YR_RND, data=api1) # creation of a simple linear model for API00 using the regressors Growth, Emer and Yr_rnd.

##creation of the function according to Arai:
clx <- function(fm, dfcw, cluster) {
    library(sandwich)
    library(lmtest)
    library(zoo)
    M <- length(unique(cluster))
    N <- length(cluster)
    dfc <- (M/(M-1))*((N-1)/(N-fm$rank)) # anpassung der freiheitsgrade
    u <- apply(estfun(fm),2, function(x) tapply(x, cluster, sum))
    vcovCL <-dfc * sandwich (fm, meat = crossprod(u)/N) * dfcw
    coeftest(fm, vcovCL)
}

clx(modell.api, 1, api1$DNUM) #creation of results.

1
Папір Араї більше не в Інтернеті. Чи можете ви надати фактичне посилання?
MERose

@MERose - Вибачте! На жаль, ми не можемо прикріпити pdfs! Я знайшов цю публікацію в блозі, яка визначає код. Я відредагую цю відповідь, щоб включити код.
Річард Херрон


4

Найпростіший спосіб обчислити кластеризовані стандартні помилки в R - це використовувати модифіковану підсумкову функцію.

lm.object <- lm(y ~ x, data = data)
summary(lm.object, cluster=c("c"))

Є чудовий пост щодо кластеризації в межах lm. На сайті також передбачена змінена підсумкова функція для одно- та двостороннього кластеризації. Ви можете знайти функцію та підручник тут .


1

Якщо у вас немає timeіндексу, він вам не потрібен: plmдодасть вигаданий сам по собі, і він не буде використаний, якщо ви цього не попросите. Отже, цей дзвінок повинен працювати :

> x <- plm(price ~ carat, data = diamonds, index = "cut")
 Error in pdim.default(index[[1]], index[[2]]) : 
  duplicate couples (time-id) 

За винятком того, що це не так, це говорить про те, що ви потрапили в помилку plm. (Ця помилка тепер виправлена ​​у SVN. Версію для розробки можна встановити тут .)

Але оскільки це все-таки був би фіктивним timeіндексом, ми можемо створити його самостійно:

diamonds$ftime <- 1:NROW(diamonds)  ##fake time

Тепер це працює:

x <- plm(price ~ carat, data = diamonds, index = c("cut", "ftime"))
coeftest(x, vcov.=vcovHC)
## 
## t test of coefficients:
## 
##       Estimate Std. Error t value  Pr(>|t|)    
## carat  7871.08     138.44  56.856 < 2.2e-16 ***
## ---
## Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Важливе зауваження : vcovHC.plm()в plmза замовчуванням буде оцінкою Арельяно кластерного груповий СЕП. Що відрізняється від оцінки vcovHC.lm()в sandwichоцінці (наприклад, vcovHCПЕ в первісному запитанні), що є гетеросцедастичністю ПЕ, без кластеризації.


Окремий підхід до цього дотримується lmфіктивних змінних регресій та пакету multiwayvcov .

library("multiwayvcov")
fe.lsdv <- lm(price ~ carat + factor(cut) + 0, data = diamonds)
coeftest(fe.lsdv, vcov.= function(y) cluster.vcov(y, ~ cut, df_correction = FALSE))
## 
## t test of coefficients:
## 
##                      Estimate Std. Error t value  Pr(>|t|)    
## carat                 7871.08     138.44  56.856 < 2.2e-16 ***
## factor(cut)Fair      -3875.47     144.83 -26.759 < 2.2e-16 ***
## factor(cut)Good      -2755.14     117.56 -23.436 < 2.2e-16 ***
## factor(cut)Very Good -2365.33     111.63 -21.188 < 2.2e-16 ***
## factor(cut)Premium   -2436.39     123.48 -19.731 < 2.2e-16 ***
## factor(cut)Ideal     -2074.55      97.30 -21.321 < 2.2e-16 ***
## ---
## Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

В обох випадках ви отримаєте SE з Arellano (1987) з групуванням по групах. multiwayvcovПакет є прямий і значною еволюцією оригінальних функцій кластеризації Араи.

Ви також можете переглянути отриману дисперсію-коваріаційну матрицю з обох підходів, даючи однакову оцінку дисперсії для carat:

vcov.plm <- vcovHC(x)
vcov.lsdv <- cluster.vcov(fe.lsdv, ~ cut, df_correction = FALSE)
vcov.plm
##          carat
## carat 19165.28
diag(vcov.lsdv)
##                carat      factor(cut)Fair      factor(cut)Good factor(cut)Very Good   factor(cut)Premium     factor(cut)Ideal 
##            19165.283            20974.522            13820.365            12462.243            15247.584             9467.263 

Перейдіть за цим посиланням:
multiwayvcov
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.