# install.packages("tidyverse")
library(dplyr)
library(tibble)
set.seed(0)
d <- tibble(
fm = c(rep("A", 5), rep("B", 5), rep("C", 5), rep("D", 5)),
yr = rep(c(1985, 1986, 1987, 1988, 1989), 4),
y = rnorm(length(yr)),
x = rnorm(length(yr))
) %>%
mutate(shock = ifelse(yr == 1988, 1, 0))
In light of more recent posts on this topic, I thought I would highlight that R uses variable ordering to break collinearity. For example, factor(fm) - 1
in the first run and factor(yr) - 1
in the second run may give the impression that we are explicitly deciding which factor level to drop; this is not the case. Software makes compromises based upon variable ordering. Here is your first model:
summary(lm(y ~ -1 + x + factor(fm) + factor(yr), data = d))
where I moved the -1
to the right of the tilde to avoid any confusion. Here, the -1
removes the intercept (i.e., column of 1's). The next variable, proceeding from left to right, is the firm fixed effects denoted by factor(fm)
; all levels will now be estimated. The third variable is the year fixed effects denoted by factor(yr)
. One level (i.e., 1985) must be dropped. Remember that all columns representing your firm dummies sum to unity, so R is going to drop a year effect to break the collinearity. See the abridged output below:
Call:
lm(formula = y ~ -1 + x + factor(fm) + factor(yr), data = d)
Coefficients:
Estimate Std. Error t value Pr(>|t|)
x 0.17232 0.42894 0.402 0.696
factor(fm)A 0.74338 0.71286 1.043 0.319
factor(fm)B -0.07289 0.69443 -0.105 0.918
factor(fm)C -0.32696 0.69275 -0.472 0.646
factor(fm)D -0.47447 0.75862 -0.625 0.544
factor(yr)1986 -0.50005 0.77809 -0.643 0.534
factor(yr)1987 -0.15720 0.82354 -0.191 0.852
factor(yr)1988 0.38128 0.78301 0.487 0.636
factor(yr)1989 0.33454 0.77855 0.430 0.676
Now suppose we swap the firm and year effects. The model has the same structure as before:
summary(lm(y ~ -1 + x + factor(yr) + factor(fm), data = d))
where we still introduce -1
inside of the lm()
function but now the firm fixed effects are third in precedence. As a consequence, software will exclude a firm. As before, your series of year dummies sum to unity, so now a firm effect is dropped from estimation. See the abridged output below:
Call:
lm(formula = y ~ -1 + x + factor(yr) + factor(fm), data = d)
Coefficients:
Estimate Std. Error t value Pr(>|t|)
x 0.1723 0.4289 0.402 0.696
factor(yr)1985 0.7434 0.7129 1.043 0.319
factor(yr)1986 0.2433 0.7349 0.331 0.747
factor(yr)1987 0.5862 0.7015 0.836 0.421
factor(yr)1988 1.1247 0.6945 1.619 0.134
factor(yr)1989 1.0779 0.6981 1.544 0.151
factor(fm)B -0.8163 0.7025 -1.162 0.270
factor(fm)C -1.0703 0.7171 -1.493 0.164
factor(fm)D -1.2179 0.7067 -1.723 0.113
Ordering wouldn't matter in this context if the intercept was included. It should be clear that one of the firm dummies and one of the year dummies will be collinear with the column of 1's appended to the model matrix. Run a third model but on this trial do not drop the intercept. It should result in 3 separate firm effects and 4 separate year effects. I am not sure why all estimates of x
in the previous answer aren't equivalent (well noted by @SextusEmpiricus); they should be similar.
A even better demonstration of how R breaks collinearity is when your model incorporates a redundant predictor at the level of $i$ or $t$. Suppose you suspect a macro level shock hit firms in 1988. You model the shock by including a time dummy specific to all entities in your panel. I will run one model with the shock preceding the time effects, then I will follow with a second run including the shock after the time effects. Here is the first run:
Call:
lm(formula = y ~ x + factor(fm) + shock + factor(yr), data = d)
Coefficients: (1 not defined because of singularities)
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.7434 0.7129 1.043 0.319
x 0.1723 0.4289 0.402 0.696
factor(fm)B -0.8163 0.7025 -1.162 0.270
factor(fm)C -1.0703 0.7171 -1.493 0.164
factor(fm)D -1.2179 0.7067 -1.723 0.113
shock 0.3813 0.7830 0.487 0.636
factor(yr)1986 -0.5001 0.7781 -0.643 0.534
factor(yr)1987 -0.1572 0.8235 -0.191 0.852
factor(yr)1988 NA NA NA NA
factor(yr)1989 0.3345 0.7785 0.430 0.676
Note the 1988 time shock precedes the year fixed effects in variable ordering. One year effect must be dropped to break the collinearity; R goes to the time effects. Now I will swap the ordering and re-estimate the model:
Call:
lm(formula = y ~ x + factor(fm) + factor(yr) + shock, data = d)
Coefficients: (1 not defined because of singularities)
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.7434 0.7129 1.043 0.319
x 0.1723 0.4289 0.402 0.696
factor(fm)B -0.8163 0.7025 -1.162 0.270
factor(fm)C -1.0703 0.7171 -1.493 0.164
factor(fm)D -1.2179 0.7067 -1.723 0.113
factor(yr)1986 -0.5001 0.7781 -0.643 0.534
factor(yr)1987 -0.1572 0.8235 -0.191 0.852
factor(yr)1988 0.3813 0.7830 0.487 0.636
factor(yr)1989 0.3345 0.7785 0.430 0.676
shock NA NA NA NA
Here, R drops shock
as it is specified after the time effects. Remember, the year fixed effects represent the common shocks in each year affecting all firms, and so the time dummy modeling the shock in 1988 is redundant with the year fixed effects.
This is yet another example of when ordering matters.