Skip to contents

Provides how the small sample correction should be calculated in vcov.fixest/summary.fixest.

Usage

ssc(
  K.adj = TRUE,
  K.fixef = "nonnested",
  K.exact = FALSE,
  G.adj = TRUE,
  G.df = "min",
  t.df = "min",
  ...
)

Arguments

K.adj

Logical scalar, defaults to TRUE. Whether to apply a small sample adjustment of the form (n - 1) / (n - K), with K the number of estimated parameters. If FALSE, then no adjustment is made.

K.fixef

Character scalar equal to "nonnested" (default), "none" or "full". In the small sample adjustment, how to account for the fixed-effects parameters. If "none", the fixed-effects parameters are discarded, meaning the number of parameters (K) is only equal to the number of variables. If "full", then the number of parameters is equal to the number of variables plus the number of fixed-effects. Finally, if "nonnested", then the number of parameters is equal to the number of variables plus the number of fixed-effects that are not nested in the clusters used to cluster the standard-errors.

When the standard-errors are not clustered, "nonnested" is equivalent to "full".

K.exact

Logical, default is FALSE. If there are 2 or more fixed-effects, these fixed-effects can be irregular, meaning they can provide the same information. If so, the "real" number of parameters should be lower than the total number of fixed-effects. If K.exact = TRUE, then fixef.fixest is first run to determine the exact number of parameters among the fixed-effects. Mostly, panels of the type individual-firm require K.exact = TRUE (but it adds computational costs).

G.adj

Logical scalar, default is TRUE. How to make the small sample correction with cluster-like standard-errors? If TRUE a G/(G-1) correction is performed with G the number of cluster values. In the case of Newey-West or Driscoll-Kraay, G is the number of time periods.

G.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 G.df="conventional" then the i-th "sandwich" matrix is adjusted with G_i/(G_i-1) with G_i the number of unique clusters.

t.df

Either "conventional", "min" (default) or an integer scalar. Only relevant when the variance-covariance matrix is cluster-like. 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 minus one. If t.df="conventional", then the degrees of freedom of the Student t distribution is equal to the number of observations minus the number of estimated variables. You can also pass a number to manually specify the DoF of the t-distribution.

In the case of Newey-West or Driscoll-Kraay, when t.df="min", this leads to using the number of time periods minus one for the degrees of freedom of the t distribution.

...

Only used internally (to catch deprecated parameters).

Value

It returns a ssc_type object.

Details

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.

Author

Laurent Berge

Examples


#
# 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)
#> VCOV type:  IID 
#>                   (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 ssc(K.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, ssc = ssc(K.adj = FALSE)) / vcov(res_glm)
#> VCOV type:  IID 
#>                   (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, ssc = ssc(K.adj = FALSE)) / vcov(res_glm_gamma)
#> VCOV type:  IID 
#>                   (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: K.fixef = "nonnested"
#  => 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.704281   0.222128  3.1706  0.08673 .  
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> RMSE: 0.360579     Adj. R2: -0.101955
#>                  Within R2:  0.538111
attributes(vcov(est, attr = TRUE))[c("ssc", "df.K")]
#> $ssc
#> Small sample correction for Clustered VCOV:
#> K.adj = TRUE, K.fixef = "nonnested", K.exact = FALSE
#> G.adj = TRUE, G.df = "min", t.df = "min"
#> 
#> $df.K
#> [1] 6
#> 


# K.fixef = FALSE
#  => adjustment K = 1 (i.e. only x)
summary(est, ssc = ssc(K.fixef = "none"))
#> 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.704281   0.148086 4.75591  0.04148 *  
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> RMSE: 0.360579     Adj. R2: -0.101955
#>                  Within R2:  0.538111
attr(vcov(est, ssc = ssc(K.fixef = "none"), attr = TRUE), "df.K")
#> [1] 1


# K.fixef = TRUE
#  => adjustment K = 1 + 3 + 5 - 1 (i.e. x + fe1 + fe2 - 1 restriction)
summary(est, ssc = ssc(K.fixef = "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.704281   0.314137 2.24196  0.15421 
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> RMSE: 0.360579     Adj. R2: -0.101955
#>                  Within R2:  0.538111
attr(vcov(est, ssc = ssc(K.fixef = "full"), attr = TRUE), "df.K")
#> [1] 8


# K.fixef = TRUE & K.exact = TRUE
#  => adjustment K = 1 + 3 + 5 - 2 (i.e. x + fe1 + fe2 - 2 restrictions)
summary(est, ssc = ssc(K.fixef = "full", K.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.704281   0.256492 2.74582  0.11099 
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> RMSE: 0.360579     Adj. R2: -0.101955
#>                  Within R2:  0.538111
attr(vcov(est, ssc = ssc(K.fixef = "full", K.exact = TRUE), attr = TRUE), "df.K")
#> [1] 7

# There are two restrictions:
attr(fixef(est), "references")
#> NOTE: The fixed-effects are not regular, they cannot be straightforwardly interpreted.
#> fe1 fe2 
#>   0   2 

#
# To permanently set the default ssc:
#

# eg no small sample adjustment for iid VCOV:
setFixest_ssc(ssc(K.adj = FALSE), "iid")

# Restoring the default for all vcovs
setFixest_ssc(vcov_names = "all")