# Why the discrepancy between the classic definition of contrast and that in R

According to Wikipedia, contrast is defined as follows:

Let $\theta_1$,$\ldots$,$\theta_t$ be a set of variables, either parameters or statistics, and $a_1$,$\ldots$,$a_t$ be known constants. The quantity $\sum_{i=1}^t a_i \theta_i$ is a linear combination. It is called a contrast if $\sum_{i=1}^t a_i = 0.$

However, if you try to use contrasts function in R, you get following:

> require(readr)
> hsb2$race.f <- factor(hsb2$race, labels=c("Hispanic", "Asian", "African-Am", "Caucasian"))
> contrasts(hsb2$race.f) Asian African-Am Caucasian Hispanic 0 0 0 Asian 1 0 0 African-Am 0 1 0 Caucasian 0 0 1  In other words, both marginal sums do not equal to 0. Why? ## 2 Answers This depends on the context in which you are using contrasts. contrasts in R is generally used to define contrasts for factors, but is not used in ANOVA or regression. For that, there are different type of contrast methods -- see ?contr.sum for the help function and the other possibilities of contr.*. The wikipedia snippet only covers one type of specific contrast, if you would like to generate this in R, use the contr.sum function which ensures that the contrasts sum to zero. [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!!