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簇数,是残差对于观测值,是预测变量的行向量,包括常数(在Wooldridge的“ 横截面”和“面板数据”中也显示为等式(7.22)ÙĴ=ΣÇü小号ËřĴë*Xñçëħ

V^CüsŤË[R=XX-1个Ĵ=1个ñCüĴüĴXX-1个
üĴ=CüsŤË[R ĴË一世X一世ñCË一世一世ŤHX一世)。但是以下代码给出了非常大的协方差矩阵。考虑到我拥有的群集数量很少,这些值是否非常大?鉴于我无法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中完成吗?这是计量经济学中相当普遍的技术(本讲座中有一个简短的教程),但我无法在R中弄清楚。谢谢!


7
@ricardh,诅咒所有经济学家不要检查他们想使用的术语是否已经在统计中使用。在这种情况下,聚类表示分组,并且与聚类分析完全无关,这就是rseek给您不相关结果的原因。因此,我删除了聚类标签。对于面板数据分析,请检查软件包plm。它有一个漂亮的小插图,所以您可能会找到想要的东西。至于你的问题,不清楚你想要什么。组内标准错误?
mpiktas 2011年

@ricardh,如果您可以链接到cluster解释该选项的一些Stata手册,将会很有帮助。我相信这将是可能的R.复制
mpiktas

2
对该评论+1。经济学家疯狂地殖民术语。尽管有时候很难选择小人。我花了一段时间,例如直到我意识到与factor它无关,factanal而是指分类变量。但是R中的簇是指簇分析,k均值只是THE分区方法:statmethods.net/advstats/cluster.html。我没有收到您的问题,但我也猜想群集与它无关。
hans0l0 2011年

@ mpiktas,@ ran2-谢谢!我希望我澄清这个问题。简而言之,如果“标准错误聚类”只是已经存在的固定效应,为什么会存在?
理查德·赫伦

1
“ multiwayvcov”软件包中的cluster.vcov函数可以满足您的需求。

Answers:


29

对于使用plm框架按组聚类的White标准错误,请尝试

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

model.plmplm模型在哪里。

另请参阅此链接

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/faculty/petersen/htm/papers/se/se_programming.htm

编辑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框架内进行集群的解决方案。

Mahmood Arai撰写的精彩白皮书提供了有关lm框架中群集的教程,他通过自由度校正来完成该工作,而不是上面的麻烦尝试。他在此处提供了针对单向和双向聚类协方差矩阵的功能。

最后,尽管内容不是免费提供的,但是Angrist和Pischke的《几乎无害计量经济学》中有一个关于聚类的部分非常有用。


2015年4月27日更新,从博客文章中添加代码。

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-对不起!不幸的是我们无法附加pdf文件!我发现此博客文章对代码进行了基准测试。我将编辑此答案以包括代码。
理查德·赫伦

这可能是白皮书的更新版本:Mahmood Arai,使用R的群集鲁棒标准错误
gung-恢复莫妮卡

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()in plm会根据SE SE组对Arellano进行估算。这是不同的东西vcovHC.lm()sandwich将估计(如vcovHC在原来的问题SES)​​,即异方差一致的社会企业,没有集群。


解决此问题的另一种方法是坚持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

在这两种情况下,您都将获得Arellano(1987)SE,并按组进行聚类。该multiwayvcov软件包是Arai原始聚类功能的直接且重要的发展。

您还可以查看两种方法的结果方差-协方差矩阵,得出以下相同的方差估计值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已
过时
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.