Provides how the degrees of freedom should be calculated in vcov.fixest
/summary.fixest
.
dof( adj = TRUE, fixef.K = "nested", cluster.adj = TRUE, cluster.df = "min", t.df = "min", fixef.force_exact = FALSE ) setFixest_dof(dof.type = dof()) getFixest_dof
adj | Logical scalar, defaults to |
---|---|
fixef.K | Character scalar equal to |
cluster.adj | Logical scalar, default is |
cluster.df | Either "conventional" or "min" (default). Only relevant when the variance-covariance matrix is two-way clustered (or higher). It governs how the small sample adjustment for the clusters is to be performed. [Sorry for the jargon that follows.] By default a unique adjustment is made, of the form G_min/(G_min-1) with G_min the smallest G_i. If |
t.df | Either "conventional" or "min" (default). Only relevant when the variance-covariance matrix is clustered. It governs how the p-values should be computed. By default, the degrees of freedom of the Student t distribution is equal to the minimum size of the clusters with which the VCOV has been clustered. If |
fixef.force_exact | Logical, default is |
dof.type | An object of class |
An object of class function
of length 1.
It returns a dof.type
object.
The following vignette: On standard-errors, describes in details how the standard-errors are computed in fixest
and how you can replicate standard-errors from other software.
Laurent Berge
# # Equivalence with lm/glm standard-errors # # LM # In the absence of fixed-effects, # by default, the standard-errors are computed in the same way res = feols(Petal.Length ~ Petal.Width + Species, iris) res_lm = lm(Petal.Length ~ Petal.Width + Species, iris) vcov(res) / vcov(res_lm)#> (Intercept) Petal.Width Speciesversicolor Speciesvirginica #> (Intercept) 1 1 1 1 #> Petal.Width 1 1 1 1 #> Speciesversicolor 1 1 1 1 #> Speciesvirginica 1 1 1 1# GLM # By default, there is no small sample adjustment in glm, as opposed to feglm. # To get the same SEs, we need to use dof(adj = FALSE) res_pois = fepois(round(Petal.Length) ~ Petal.Width + Species, iris) res_glm = glm(round(Petal.Length) ~ Petal.Width + Species, iris, family = poisson()) vcov(res_pois, dof = dof(adj = FALSE)) / vcov(res_glm)#> (Intercept) Petal.Width Speciesversicolor Speciesvirginica #> (Intercept) 1 1 1 1 #> Petal.Width 1 1 1 1 #> Speciesversicolor 1 1 1 1 #> Speciesvirginica 1 1 1 1# Same example with the Gamma res_gamma = feglm(round(Petal.Length) ~ Petal.Width + Species, iris, family = Gamma()) res_glm_gamma = glm(round(Petal.Length) ~ Petal.Width + Species, iris, family = Gamma()) vcov(res_gamma, dof = dof(adj = FALSE)) / vcov(res_glm_gamma)#> (Intercept) Petal.Width Speciesversicolor Speciesvirginica #> (Intercept) 1 1 1 1 #> Petal.Width 1 1 1 1 #> Speciesversicolor 1 1 1 1 #> Speciesvirginica 1 1 1 1# # Fixed-effects corrections # # We create "irregular" FEs base = data.frame(x = rnorm(10)) base$y = base$x + rnorm(10) base$fe1 = rep(1:3, c(4, 3, 3)) base$fe2 = rep(1:5, each = 2) est = feols(y ~ x | fe1 + fe2, base) # fe1: 3 FEs # fe2: 5 FEs # # Clustered standard-errors: by fe1 # # Default: fixef.K = "nested" # => adjustment K = 1 + 5 (i.e. x + fe2) summary(est)#> OLS estimation, Dep. Var.: y #> Observations: 10 #> Fixed-effects: fe1: 3, fe2: 5 #> Standard-errors: Clustered (fe1) #> Estimate Std. Error t value Pr(>|t|)) #> x 0.079171 0.281686 0.281061 0.805072 #> --- #> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 #> RMSE: 0.873241 Adj. R2: -1.7512 #> Within R2: 0.003658#> $dof.type #> [1] "dof(adj = TRUE, fixef.K = 'nested', cluster.adj = TRUE, cluster.df = 'min', t.df = 'min', fixef.force_exact = FALSE)" #> #> $dof.K #> [1] 6 #>#> OLS estimation, Dep. Var.: y #> Observations: 10 #> Fixed-effects: fe1: 3, fe2: 5 #> Standard-errors: Clustered (fe1) #> Estimate Std. Error t value Pr(>|t|)) #> x 0.079171 0.187791 0.421592 0.714314 #> --- #> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 #> RMSE: 0.873241 Adj. R2: -1.7512 #> Within R2: 0.003658#> [1] 1# fixef.K = TRUE # => adjustment K = 1 + 3 + 5 - 1 (i.e. x + fe1 + fe2 - 1 restriction) summary(est, dof = dof(fixef.K = "full"))#> OLS estimation, Dep. Var.: y #> Observations: 10 #> Fixed-effects: fe1: 3, fe2: 5 #> Standard-errors: Clustered (fe1) #> Estimate Std. Error t value Pr(>|t|)) #> x 0.079171 0.398364 0.19874 0.860837 #> --- #> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 #> RMSE: 0.873241 Adj. R2: -1.7512 #> Within R2: 0.003658#> [1] 8# fixef.K = TRUE & fixef.force_exact = TRUE # => adjustment K = 1 + 3 + 5 - 2 (i.e. x + fe1 + fe2 - 2 restrictions) summary(est, dof = dof(fixef.K = "full", fixef.force_exact = TRUE))#> OLS estimation, Dep. Var.: y #> Observations: 10 #> Fixed-effects: fe1: 3, fe2: 5 #> Standard-errors: Clustered (fe1) #> Estimate Std. Error t value Pr(>|t|)) #> x 0.079171 0.325263 0.243406 0.83038 #> --- #> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 #> RMSE: 0.873241 Adj. R2: -1.7512 #> Within R2: 0.003658#> [1] 7#>#> fe1 fe2 #> 0 2# # To permanently set the default dof: # # eg no small sample adjustment: setFixest_dof(dof(adj = FALSE)) # Factory default setFixest_dof()