rlmcontrastmodel.matrix

A linear model matrix where each level of a categorical is contrasted with the mean


I have xy data, where y is a continuous response and x is a categorical variable:

set.seed(1)
df <- data.frame(y = rnorm(27), group = c(rep("A",9),rep("B",9),rep("C",9)), stringsAsFactors = F)

I would like to fit the linear model: y ~ group to it, in which each of the levels in df$group is contrasted with the mean.

I thought that using Deviation Coding does that:

lm(y ~ group,contrasts = "contr.sum",data=df)

But it skips contrasting group A with the mean:

> summary(lm(y ~ group,contrasts = "contr.sum",data=df))

Call:
lm(formula = y ~ group, data = df, contrasts = "contr.sum")

Residuals:
    Min      1Q  Median      3Q     Max 
-1.6445 -0.6946 -0.1304  0.6593  1.9165 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)  -0.2651     0.3457  -0.767    0.451
groupB        0.2057     0.4888   0.421    0.678
groupC        0.3985     0.4888   0.815    0.423

Residual standard error: 1.037 on 24 degrees of freedom
Multiple R-squared:  0.02695,   Adjusted R-squared:  -0.05414 
F-statistic: 0.3324 on 2 and 24 DF,  p-value: 0.7205

Is there any function that builds a model matrix to get each of the levels of df$group contrasted with the mean in the summary?

All I can think of is manually adding a "mean" level to df$group and setting it is as baseline with Dummy Coding:

df <- df %>% rbind(data.frame(y = mean(df$y), group ="mean"))
df$group <- factor(df$group, levels = c("mean","A","B","C"))
summary(lm(y ~ group,contrasts = "contr.treatment",data=df))

Call:
lm(formula = y ~ group, data = df, contrasts = "contr.treatment")

Residuals:
     Min       1Q   Median       3Q      Max 
-2.30003 -0.34864  0.07575  0.56896  1.42645 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)  0.14832    0.95210   0.156    0.878
groupA       0.03250    1.00360   0.032    0.974
groupB      -0.06300    1.00360  -0.063    0.950
groupC       0.03049    1.00360   0.030    0.976

Residual standard error: 0.9521 on 24 degrees of freedom
Multiple R-squared:  0.002457,  Adjusted R-squared:  -0.1222 
F-statistic: 0.01971 on 3 and 24 DF,  p-value: 0.9961

Similarly, suppose I have data with two categorical variables:

set.seed(1)
df <- data.frame(y = rnorm(18),
                 group = c(rep("A",9),rep("B",9)),
                 class = as.character(rep(c(rep(1,3),rep(2,3),rep(3,3)),2)))

and I would like to estimate the interaction effect per each level: (i.e., class1:groupB, class2:groupB, and class3:groupB for:

lm(y ~ class*group,contrasts = c("contr.sum","contr.treatment"),data=df)

How would I obtain it?


Solution

  • Use +0 in the lm formula to omit the intercept, then you should get the expected contrast coding:

    summary(lm(y ~ 0 + group, contrasts = "contr.sum", data=df))
    

    Result:

    Call:
    lm(formula = y ~ 0 + group, data = df, contrasts = "contr.sum")
    
    Residuals:
        Min      1Q  Median      3Q     Max 
    -2.3000 -0.3627  0.1487  0.5804  1.4264 
    
    Coefficients:
           Estimate Std. Error t value Pr(>|t|)
    groupA  0.18082    0.31737   0.570    0.574
    groupB  0.08533    0.31737   0.269    0.790
    groupC  0.17882    0.31737   0.563    0.578
    
    Residual standard error: 0.9521 on 24 degrees of freedom
    Multiple R-squared:  0.02891,   Adjusted R-squared:  -0.09248 
    F-statistic: 0.2381 on 3 and 24 DF,  p-value: 0.8689
    

    If you want to do this for an interaction, here's one way:

    lm(y ~ 0 + class:group,
        contrasts = c("contr.sum","contr.treatment"), 
        data=df)