[note: for all those people who got here confused after reading section 9 of the UCLA post on contrast matrices, this will help. after hours of head banging, here's what I figured out]
Please use the following demos to convince yourself of the similarities / difference / relationship between contrasts [sometimes called design matrices?] and the thing you see in R [contrast matrix].
In essence, R uses the contrast matrix to generate "dummy variables" that represent the factor in the model. You need to convert the contrasts into an appropriate coding matrix.
Please use the following code to convince yourself of the relationship between the two:
First, let look at dummy coding or treatment coding
hsb2 = read.table('http://www.ats.ucla.edu/stat/data/hsb2.csv', header=T, sep=",")
#creating the factor variable race.f
hsb2$race.f = factor(hsb2$race, labels=c("Hispanic", "Asian", "African-Am", "Caucasian"))
#================================================================
# =: Dummy Coding [normal intercept] :=
#================================================================
# This is just a quick way to create what you would normally consider
# a simple "treatment" coding or "dummy coding" matrix
dummy.coding <- rbind(c(1,-1,-1,-1),
c(0, 1, 0, 0),
c(0, 0, 1, 0),
c(0, 0, 0, 1))
rownames(dummy.coding) <- c("control", "L1","L2","L3")
colnames(dummy.coding) <- c("intercept", "L1 vs Control","L2 vs Control","L3 vs Control")
# Column 2:4 is what you would normally consider the contrast
# And, as you can see, they add to zero
dummy.coding
# Now, to get the coding matrix that R will use,
# you need to take the inverse of the transpose of this matrix
# and, drop the first column
coding.matrix <- solve(t(dummy.coding))[,-1]
coding.matrix
# To convince yourself, this is correct, compare it to the
# inbuilt R function:
contr.treatment(4)
# Now, using the dataset that you cited from the UCLA page
# You can see the what R is doing under the hood:
# First, we assign
contrasts(hsb2$race.f) = coding.matrix
# Now, we look at the model matrix
View(cbind(as.character(hsb2$race.f), model.matrix(~race.f, data=hsb2)))
# So, essentially, R took that coding matrix and
# generated dummy variables
# Now, see the linear model:
summary(lm(formula = write ~ race.f, data = temp.hsb2))
OK, having done the basic case, lets extend it. In the above example, the intercept of the model was the "control" variable.
Notice that the final coding matrix did not include a column for the intercept. That is because the inverse of the transpose of the contrast matrix (dummy.coding) baked it into the final outcome: coding.matrix.
Simple Coding
So, now, lets look at a case where we want the intercept to represent the grand mean (i.e. mean of means). This is sometimes called simple coding.
Here, we just set the first column of the contrast matrix to the same value.
#============================================================
#=: Dummy Coding [grand mean intercept i.e. simple coding] :=
#============================================================
dummy.coding.GM.intercept <- rbind(c(1,-1,-1,-1),
c(1, 1, 0, 0),
c(1, 0, 1, 0),
c(1, 0, 0, 1))
rownames(dummy.coding.GM.intercept) <- c("control", "L1","L2","L3")
colnames(dummy.coding.GM.intercept) <- c("intercept: GM", "L1 vs Control","L2 vs Control","L3 vs Control")
dummy.coding.GM.intercept
coding.matrix <- solve(t(dummy.coding.GM.intercept))[,-1]
coding.matrix
contrasts(hsb2$race.f) = coding.matrix
# Now, see the linear model and compare the intercepts:
summary(lm(formula = write ~ race.f, data = temp.hsb2))
Deviation Coding or Effects Coding
Finally, lets look at another common case. Here, we want to have contrasts that compare a given level of a factor to the grand mean of the variable. This is sometimes called effects coding, deviation coding, or sum contrasts.
#=======================================================
# =: Deviation Coding [intercept: grand mean] :=
#=======================================================
deviation.coding <- cbind(c( 0.25, 0.25, 0.25, 0.25),
c( 0.75, -0.25, -0.25, -0.25),
c(-0.25, 0.75, -0.25, -0.25),
c(-0.25, -0.25, 0.75, -0.25))
rownames(deviation.coding) <- c("L1","L2","L3", "L4")
colnames(deviation.coding) <- c("intercept: GM", "L1 vs GM","L2 vs GM","L3 vs GM")
deviation.coding
# Now, to get the coding matrix that R will use,
# you need to take the inverse of the transpose of this matrix
# and, drop the first column
coding.matrix <- solve(t(deviation.coding))[,-1]
coding.matrix
# To convince yourself, this is correct, compare it to the
# inbuilt R function:
contr.sum(4)
# Now, using the dataset that you cited from the UCLA page
# You can see the what R is doing under the hood:
# First, we assign
contrasts(hsb2$race.f) = coding.matrix
# Now, we look at the model matrix
View(cbind(as.character(hsb2$race.f), model.matrix(~race.f, data=hsb2)))
# So, essentially, R took that coding matrix and
# generated variables with EFFECTS CODING
So, there's that. Hope this helps!!