Why Choose Custom Contrasts?
A factor with several levels can represent comparisons that matter more than a collection of differences from one arbitrarily chosen reference level. For example, a study might be designed to compare a treatment with the average of two controls, or to compare a candidate product with a weighted benchmark. Custom contrasts let the model encode those planned questions directly.
A contrast is a weighted sum of level means whose weights add to zero. The zero-sum condition makes the comparison independent of an overall shift in all level means. The coding used in R then determines how that comparison appears among the fitted model coefficients.
The contrast weights \(c_j\) define the quantity of interest. The coding column \(d_j\) used to represent it in a model is not necessarily the same vector: a suitable scale and a complete set of other contrast columns are needed if the model coefficient is to equal \(L\) itself. This distinction is essential when interpreting coefficients.
A Three-Level Planned Comparison
Suppose a hypothetical study compares two control protocols, C1 and C2, with a treatment, T. Let their fitted level means be \(\mu_{C1}\), \(\mu_{C2}\), and \(\mu_T\). A natural planned comparison is treatment versus the average of the two controls:
The weights are \((-1/2,-1/2,1)\), which sum to zero. To make the coefficient for this comparison equal to \(L\), use the coding column \((-1/3,-1/3,2/3)\). Include a second column \((1/2,-1/2,0)\) to distinguish the two controls. These columns sum to zero and are orthogonal: their elementwise products sum to zero. They are also linearly independent, so together they provide the two columns required for a three-level factor.
In R, with factor levels ordered as C1, C2, T, the matrix can be assigned as follows. The row names must match the factor levels.
R code: lev <- c("C1", "C2", "T"); C <- cbind(T_vs_avg_control = c(-1/3, -1/3, 2/3), C1_vs_C2 = c(1/2, -1/2, 0)); rownames(C) <- lev; contrasts(dat$group) <- C; fit <- lm(y ~ group, data = dat).
The less-than sign in an R formula means “regress y on group”; the factor is represented by its contrast columns. With this coding, the coefficient for groupT_vs_avg_control is the treatment mean minus the average control mean, while the coefficient for groupC1_vs_C2 is the C1 mean minus the C2 mean. The intercept is the unweighted average of the three fitted level means, not necessarily the sample-size-weighted average across all observations.
Worked Example: Interpreting Two Custom Coefficients
A hypothetical model estimates group means of 10 for C1, 14 for C2, and 20 for T. Using the coding above, find the intercept and both contrast coefficients, then check that the coding reconstructs all three means.
Method. Calculate each planned comparison from the group means. The zero-sum coding columns ensure the intercept is the unweighted average of the level means.
The intercept is:
The treatment-versus-average-control coefficient is:
The C1-versus-C2 coefficient is:
Reconstruct C1 using its coding values \((-1/3,1/2)\):
For C2, the coding values are \((-1/3,-1/2)\):
For T, the coding values are \((2/3,0)\):
The reconstructed means agree with the three supplied means. Values were rounded to four decimal places for display; the exact intercept is \(44/3\). A common mistake is to read the intercept as the control mean or as the treatment mean. Under this coding it is the unweighted average of the level means.
Why the Coefficient Equals the Planned Contrast
The link between coding and interpretation follows directly from the model representation. Let \(\boldsymbol{\mu}\) be the vector of level means, \(\mathbf{1}\) the vector of ones, and \(D\) the matrix of contrast coding columns. The fitted means are represented as \(\boldsymbol{\mu}=\alpha\mathbf{1}+D\boldsymbol{\beta}\). If every column of \(D\) sums to zero, averaging the level equations gives \(\alpha\) as the unweighted average of the level means.
For one planned contrast, let \(\mathbf{c}\) be its weight vector and choose its coding column as \(\mathbf{d}=\mathbf{c}/(\mathbf{c}^{T}\mathbf{c})\). Suppose every other coding column is orthogonal to \(\mathbf{d}\). Taking the inner product of the fitted-mean equation with \(\mathbf{d}\) removes the intercept, because \(\mathbf{d}^{T}\mathbf{1}=0\), and removes the other contrast terms by orthogonality. Therefore:
The final equality holds because \(\mathbf{d}=\mathbf{c}/(\mathbf{c}^{T}\mathbf{c})\), so \(\mathbf{d}^{T}\boldsymbol{\mu}=(\mathbf{c}^{T}\boldsymbol{\mu})/(\mathbf{c}^{T}\mathbf{c})\) and \(\mathbf{d}^{T}\mathbf{d}=1/(\mathbf{c}^{T}\mathbf{c})\). This establishes why the chosen coefficient equals the planned comparison. If another coding column is not orthogonal to \(\mathbf{d}\), its contribution need not disappear in this calculation; do not assume a coefficient has the desired interpretation merely because one coding column resembles the contrast weights.
Weighted Comparisons and Constraint Checks
Planned comparisons need not give all control levels equal weight. Suppose four hypothetical groups are A, B, C, and T, and the intended benchmark gives A one-quarter weight and B three-quarters weight. The comparison is treatment minus that weighted benchmark:
The weights \((-1/4,-3/4,0,1)\) sum to zero. To use a coefficient equal to this contrast, divide the weight vector by its squared length. Its squared length is \(1/16+9/16+1=13/8\), giving coding column \((-2/13,-6/13,0,8/13)\). The other two columns in a four-level contrast matrix must be independent, sum to zero, and be orthogonal to this column if the corresponding model coefficient is to isolate the planned comparison as in the derivation above.
Worked Example: A Weighted Treatment Benchmark
In a hypothetical four-group study, the estimated means are A = 8, B = 12, C = 16, and T = 20. The pre-specified benchmark weights A by one-quarter and B by three-quarters, with C excluded. Calculate the contrast, verify its constraint, and identify the coefficient when using the scaled coding column above with suitable orthogonal companion columns.
Method. Apply the stated weights to the benchmark first, then subtract that benchmark from the treatment mean. Do not replace the specified weighted benchmark with the ordinary average of the control groups.
The weighted benchmark is:
Thus the planned contrast is \(20-11=9\). Directly from the weights, the same result is:
The constraint check is \(-1/4-3/4+0+1=0\). The coding column is the contrast-weight vector divided by \(13/8\), so the derivation shows that its model coefficient is 9 when the other contrast columns are orthogonal to it. The result is checked both by the benchmark calculation and by the weighted sum. A comparison with the unweighted mean of A, B, and C would answer a different question.
Common Coding Traps
- Weights do not sum to zero. A proposed set of weights that sums to a nonzero value is not a contrast; it changes if the same constant is added to every group mean.
- Weights and coding columns are treated as interchangeable. The contrast weights define \(L\); the coding column may require scaling and appropriate companion columns for a coefficient to equal \(L\).
- A contrast coefficient is mistaken for a reference-level difference. A coefficient under treatment coding usually compares a level with the reference level. A custom coefficient represents the comparison specified by its coding and the other columns.
- Factor order is overlooked. Matrix rows correspond to factor levels. If the row order or names do not match the factor, the intended comparison may be assigned incorrectly or R may reject the matrix.
- Unweighted and sample-size-weighted averages are confused. With zero-sum custom contrasts and an intercept, the intercept is an unweighted average across factor levels. Unequal group sizes do not change that parameter interpretation.
For a standard linear model, the fitted group means are the observed group means when the model includes only this factor and an intercept. The contrast-coefficient identities describe the parameterization of those fitted means. Conventional standard errors and tests additionally rely on the assumptions of the fitted model; coding a planned comparison does not itself establish those assumptions. This approach is aligned with the SOA Exam PA (Predictive Analytics) syllabus because it requires both technically correct encoding and a clear interpretation tied to the analytical question.
Check Your Understanding
For each item, check the weights first, then distinguish the comparison from the coding used to represent it.
- A three-level factor has means 6, 10, and 18. The planned contrast is level 3 versus the average of levels 1 and 2. State the weights, verify the constraint, and calculate the contrast. (Answer: Weights \((-1/2,-1/2,1)\); sum \(0\); contrast \(18-(6+10)/2=10\).)
- For four levels, a proposed comparison has weights \((-1/3,-2/3,0,1)\). Is it a contrast? (Answer: Yes; the weights sum to \(0\).)
- In a three-level model, the level means are 5, 9, and 13, and the planned comparison is level 3 minus the average of levels 1 and 2. Find the contrast and the unweighted intercept under zero-sum coding. (Answer: Contrast \(13-(5+9)/2=6\); intercept \((5+9+13)/3=9\).)
- A benchmark uses weights one-quarter for A and three-quarters for B; treatment T has mean 17, A has mean 5, and B has mean 9. Calculate treatment minus the benchmark. (Answer: \(17-[0.25(5)+0.75(9)]=17-8=9\).)
- A proposed three-level comparison uses weights \((1,-1,1)\). Explain why it cannot be a contrast, and give one simple correction that retains the first two weights. (Answer: The weights sum to \(1\), not \(0\); changing the third weight to \(0\) gives \((1,-1,0)\), which sums to \(0\).)