diff --git a/DESCRIPTION b/DESCRIPTION index 486359c..5eabb0b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,8 +2,12 @@ Package: lfe Version: 2.8-4 Date: 2019-12-10 Title: Linear Group Fixed Effects -Authors@R: person("Simen", "Gaure", email="Simen.Gaure@frisch.uio.no", role=c("aut","cre"), - comment=c(ORCID="https://orcid.org/0000-0001-7251-8747")) +Authors@R: c(person("Simen", "Gaure", email="Simen.Gaure@frisch.uio.no", role=c("aut","cre"), + comment=c(ORCID="https://orcid.org/0000-0001-7251-8747")), + person("Grant","McDermott", email="grantmcd@uoregon.edu", role="ctb"), + person("Karl", "Dunkle Werner", role="ctb"), + person("Matthieu","Stigler",role="ctb"), + person("Daniel","Lüdecke",email="mail@danielluedecke.de",role="ctb")) Copyright: 2011-2018, Simen Gaure Depends: R (>= 2.15.2), Matrix (>= 1.1-2) Imports: Formula, xtable, compiler, utils, methods, sandwich, parallel diff --git a/R/felm.R b/R/felm.R index 8c09970..9b408b1 100644 --- a/R/felm.R +++ b/R/felm.R @@ -952,7 +952,7 @@ newols <- function(mm, stage1=NULL, pf=parent.frame(), nostats=FALSE, exactDOF=F #' #' \item \code{cmethod} character. Which clustering method to use. Known #' arguments are \code{'cgm'} (the default), \code{'cgm2'} (or \code{'reghdfe'}, -#' its alias), or \code{'gaure'}. These alternate methods will generally +#' its alias). These alternate methods will generally #' yield equivalent results, except in the case of multiway clustering with few #' clusters along at least one dimension. #' diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index f206fdb..f922adb 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -2,6 +2,8 @@ \title{lfe news} \section{Changes in version 2.8-4}{ \itemize{ + \item Support for nested clusters and reghdfe-option by Grant McDermott and Karl + Dunkle Werner. \item Changed some extern declarations in the C-code to comply with standards enforced by the upcoming gcc10. \item Changed inner workings of the \code{unnamed()} and diff --git a/inst/doc/index.html b/inst/doc/index.html index e2afa3b..338aa19 100644 --- a/inst/doc/index.html +++ b/inst/doc/index.html @@ -5,7 +5,7 @@

Vignettes and other documentation - +


@@ -19,26 +19,26 @@

Vignettes from package 'lfe'

-lfe::biascorrection +lfe::biascorrection Limited mobility bias correction -PDF -source +PDF +source -lfe::identification +lfe::identification Multicollinearity, identification, and estimable functions -PDF -source -R code -lfe::lfehow +PDF +source +R code +lfe::lfehow How lfe works -PDF -source -R code -lfe::speed +PDF +source +R code +lfe::speed Convergence rate with examples -PDF -source -R code +PDF +source +R code

Other files in the doc directory

diff --git a/man/felm.Rd b/man/felm.Rd index 9baa9d2..a56965f 100644 --- a/man/felm.Rd +++ b/man/felm.Rd @@ -57,7 +57,7 @@ squares is used with weights \code{weights} (that is, minimizing \item \code{cmethod} character. Which clustering method to use. Known arguments are \code{'cgm'} (the default), \code{'cgm2'} (or \code{'reghdfe'}, -its alias), or \code{'gaure'}. These alternate methods will generally +its alias). These alternate methods will generally yield equivalent results, except in the case of multiway clustering with few clusters along at least one dimension. diff --git a/tests/Examples/lfe-Ex.Rout.save b/tests/Examples/lfe-Ex.Rout.save index 776c254..b571d86 100644 --- a/tests/Examples/lfe-Ex.Rout.save +++ b/tests/Examples/lfe-Ex.Rout.save @@ -1,5 +1,5 @@ -R Under development (unstable) (2019-05-02 r76454) -- "Unsuffered Consequences" +R Under development (unstable) (2019-12-10 r77548) -- "Unsuffered Consequences" Copyright (C) 2019 The R Foundation for Statistical Computing Platform: x86_64-pc-linux-gnu (64-bit) @@ -439,8 +439,8 @@ function (v, addnames) } v } - - + + > is.estimable(ef,fl) Warning in is.estimable(ef, fl) : non-estimable function, largest error 0.003 in coordinate 1050 ("id.1050") @@ -462,8 +462,8 @@ function (v, addnames) } v } - - + + attr(,"verified") [1] TRUE > is.estimable(ef,fl) @@ -490,24 +490,24 @@ attr(,"verified") > > > oldopts <- options(lfe.threads=1) -> ## create covariates +> +> ## Simulate data +> +> # Covariates > x <- rnorm(1000) > x2 <- rnorm(length(x)) -> -> ## individual and firm +> # Individuals and firms > id <- factor(sample(20,length(x),replace=TRUE)) > firm <- factor(sample(13,length(x),replace=TRUE)) -> -> ## effects for them +> # Effects for them > id.eff <- rnorm(nlevels(id)) > firm.eff <- rnorm(nlevels(firm)) -> -> ## left hand side +> # Left hand side > u <- rnorm(length(x)) > y <- x + 0.5*x2 + id.eff[id] + firm.eff[firm] + u > -> ## estimate and print result -> est <- felm(y ~ x+x2| id + firm) +> ## Estimate the model and print the results +> est <- felm(y ~ x + x2 | id + firm) > summary(est) Call: @@ -531,24 +531,25 @@ F-statistic(full model):85.78 on 33 and 966 DF, p-value: < 2.2e-16 F-statistic(proj model): 602.1 on 2 and 966 DF, p-value: < 2.2e-16 +> > ## Not run: -> ##D ## compare with lm +> ##D # Compare with lm > ##D summary(lm(y ~ x + x2 + id + firm-1)) > ## End(Not run) > -> # make an example with 'reverse causation' -> # Q and W are instrumented by x3 and the factor x4. Report robust s.e. +> ## Example with 'reverse causation' (IV regression) +> +> # Q and W are instrumented by x3 and the factor x4. > x3 <- rnorm(length(x)) > x4 <- sample(12,length(x),replace=TRUE) -> > Q <- 0.3*x3 + x + 0.2*x2 + id.eff[id] + 0.3*log(x4) - 0.3*y + rnorm(length(x),sd=0.3) > W <- 0.7*x3 - 2*x + 0.1*x2 - 0.7*id.eff[id] + 0.8*cos(x4) - 0.2*y+ rnorm(length(x),sd=0.6) -> -> # add them to the outcome +> # Add them to the outcome variable > y <- y + Q + W > -> ivest <- felm(y ~ x + x2 | id+firm | (Q|W ~x3+factor(x4))) -> summary(ivest,robust=TRUE) +> ## Estimate the IV model and report robust SEs +> ivest <- felm(y ~ x + x2 | id + firm | (Q|W ~ x3 + factor(x4))) +> summary(ivest, robust=TRUE) Call: felm(formula = y ~ x + x2 | id + firm | (Q | W ~ x3 + factor(x4))) @@ -579,10 +580,58 @@ F-statistic(endog. vars):681.6 on 2 and 964 DF, p-value: < 2.2e-16 iid F 40.07999 66.90775 attr(,"df1") [1] 11 +> > ## Not run: -> ##D # compare with the not instrumented fit: -> ##D summary(felm(y ~ x + x2 +Q + W |id+firm)) +> ##D # Compare with the not instrumented fit: +> ##D summary(felm(y ~ x + x2 + Q + W | id + firm)) > ## End(Not run) +> +> ## Example with multiway clustering +> +> # Create a large cluster group (500 clusters) and a small one (20 clusters) +> cl1 <- factor(sample(rep(1:500, length.out=length(x)))) +> cl2 <- factor(sample(rep(1:20, length.out=length(x)))) +> # Function for adding clustered noise to our outcome variable +> cl_noise <- function(cl) { ++ obs_per_cluster <- length(x)/nlevels(cl) ++ unlist(replicate(nlevels(cl), rnorm(obs_per_cluster, mean=rnorm(1), sd=runif(1)), simplify=FALSE)) ++ } +> # New outcome variable +> y_cl <- x + 0.5*x2 + id.eff[id] + firm.eff[firm] + cl_noise(cl1) + cl_noise(cl2) +> +> ## Estimate and print the model with cluster-robust SEs (default) +> est_cl <- felm(y_cl ~ x + x2 | id + firm | 0 | cl1 + cl2) +> summary(est_cl) + +Call: + felm(formula = y_cl ~ x + x2 | id + firm | 0 | cl1 + cl2) + +Residuals: + Min 1Q Median 3Q Max +-4.8756 -0.9697 0.0232 1.0041 5.2598 + +Coefficients: + Estimate Cluster s.e. t value Pr(>|t|) +x 0.97330 0.05007 19.44 <2e-16 *** +x2 0.53359 0.03043 17.54 <2e-16 *** +--- +Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 + +Residual standard error: 1.528 on 966 degrees of freedom +Multiple R-squared(full model): 0.5746 Adjusted R-squared: 0.5601 +Multiple R-squared(proj model): 0.3633 Adjusted R-squared: 0.3415 +F-statistic(full model, *iid*):39.54 on 33 and 966 DF, p-value: < 2.2e-16 +F-statistic(proj model): 252.8 on 2 and 499 DF, p-value: < 2.2e-16 + + +> +> ## Not run: +> ##D # Print ordinary standard errors: +> ##D summary(est_cl, robust = FALSE) +> ##D # Match cluster-robust SEs from Stata's reghdfe package: +> ##D summary(felm(y_cl ~ x + x2 | id + firm | 0 | cl1 + cl2, cmethod="reghdfe")) +> ## End(Not run) +> > options(oldopts) > > @@ -1245,7 +1294,7 @@ firm -0.004334716 0.060817078 -0.002995544 foo -0.002472491 -0.002995544 0.044123684 > # estimate variances of the diagonal > varvars(est, alpha) -[1] 0.008598521 0.043820908 0.057656021 +[1] 0.008598521 0.043820907 0.057656021 > > > @@ -1294,7 +1343,7 @@ F-statistic: 5219 on 2 and 9997 DF, p-value: < 2.2e-16 0.9019639 0.5757362 3.0000000 0.9019611 0.1919121 9997.0000000 attr(,"formula") ~x - 1 | x2 + 0.2 | `(Intercept)` - + > # The Delta-method coincides when the function is linear: > waldtest(est, function(x) x - c(0, 1, -0.2)) p chi2 df1 p.F F df2 @@ -1302,7 +1351,7 @@ attr(,"formula") attr(,"formula") function (x) x - c(0, 1, -0.2) - + > > > @@ -1312,7 +1361,7 @@ x - c(0, 1, -0.2) > cleanEx() > options(digits = 7L) > base::cat("Time elapsed: ", proc.time() - base::get("ptime", pos = 'CheckExEnv'),"\n") -Time elapsed: 16.177 3.862 15.587 0 0 +Time elapsed: 25.676 0.647 13.514 0 0 > grDevices::dev.off() null device 1