We use a simple hypothetical data set to illustrate some issues when
covariate ranges do not match well. The data set consists of two
treatment groups, a single response variable (Y) and a single covariate
(X) Thie data file is here
Preliminaries
First, load the required packages (car)
Import covrange data file
covrange <- read.csv("../data/covrange.csv")
head(covrange,10)
#Make group a factor
covrange$group<-factor(covrange$group)
Fit full model with interaction to evaluate homogeneous slopes
All SS types produce same result for interaction
covrange.aov1 <- aov(y~group+x+group*x, data = covrange)
plot(covrange.aov1)




Anova(covrange.aov1, type = 3)
Anova Table (Type III tests)
Response: y
Sum Sq Df F value Pr(>F)
(Intercept) 35.700 1 40.8864 8.885e-06 ***
group 5.016 1 5.7442 0.02911 *
x 7.191 1 8.2357 0.01112 *
group:x 2.445 1 2.8005 0.11367
Residuals 13.970 16
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Not strong evidence for heterogenous slopes
Run simpler model
covrange.aov2 <- aov(y~group+x, data = covrange)
Anova(covrange.aov2, type = 3)
Anova Table (Type III tests)
Response: y
Sum Sq Df F value Pr(>F)
(Intercept) 99.269 1 102.8038 1.264e-08 ***
group 4.681 1 4.8472 0.04179 *
x 5.157 1 5.3405 0.03364 *
Residuals 16.416 17
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Get adjusted means
adjmeans <- effect("group", covrange.aov2, se = TRUE)
summary(adjmeans)
group effect
group
1 2
8.951958 10.367042
Lower 95 Percent Confidence Limits
group
1 2
8.130592 9.545677
Upper 95 Percent Confidence Limits
group
1 2
9.773323 11.188408
Use Huitema adjustment
Instead of using raw x values as covariates, Huitema suggests using
the x-residuals from each group. This is done already in the data file
(xres), but it can be done by fitting a lm with x as the response and
group as the predictor, and using the calculated residuals. We’ll skip
the comparison of slopes and just run the pooled slopes model and get
adjusted means
covrange.aov3 <- aov(y~group+xres, data = covrange)
Anova(covrange.aov3, type = 3)
Anova Table (Type III tests)
Response: y
Sum Sq Df F value Pr(>F)
(Intercept) 707.28 1 732.4627 2.033e-15 ***
group 31.23 1 32.3367 2.677e-05 ***
xres 5.16 1 5.3405 0.03364 *
Residuals 16.42 17
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
adjmeans <- effect("group", covrange.aov3, se = TRUE)
summary(adjmeans)
group effect
group
1 2
8.410 10.909
Lower 95 Percent Confidence Limits
group
1 2
7.754387 10.253387
Upper 95 Percent Confidence Limits
group
1 2
9.065613 11.564613
Generate graph
df1<-covrange # Copy dataframe to df1 so generic code can be used
aggregate(x = df1$x, # Specify data column
by = list(df1$group), # Specify group indicator
FUN = mean)
p1<-ggplot(data = df1,aes(x = x,y = y,group = group, shape = group, color = group))+
geom_point()+
geom_smooth(method = "lm",se = FALSE)+
geom_vline(xintercept = 3.872, linetype = "dashed", color = lf)+
geom_segment(x = 2.803,y = 6,xend = 2.803,yend = 7, arrow = arrow(length = unit(3, "mm")),color = lc)+
geom_segment(x = 4.94,y = 6,xend = 4.94,yend = 7, arrow = arrow(length = unit(3, "mm")),color = lc)+
labs(x = "X", y = NULL)+
scale_color_grey(end = 0.6)+
theme_qk()+
theme(
legend.position = "none"
)
p2<-ggplot(data = df1,aes(x = xres,y = y,group = group, shape = group, color = group))+
geom_point()+
geom_smooth(method = "lm",se = FALSE)+
geom_vline(xintercept = 0, linetype = "dashed", color = lf)+
labs(x = "X residual", y = NULL)+
scale_color_grey(end = 0.6)+
theme_qk()+
theme(
legend.position = "none"
)
p3<-ggplot(data = df1,aes(x = x,y = y))+
geom_point(color = sc)+
geom_smooth(method = "lm",se = FALSE, color = sc,linetype = "dashed")+
geom_smooth(method = "loess", color = lc, linetype = "solid", se = FALSE, span = 2)+
labs(x = "X", y = NULL)+
scale_color_grey(end = 0.6)+
theme_qk()+
theme(
legend.position = "none"
)
p1+p2+p3

LS0tCnRpdGxlOiAiUUsgQm94IDguMTUiCgpvdXRwdXQ6IAogaHRtbF9ub3RlYm9vazoKICB0aGVtZTogZmxhdGx5Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCldlIHVzZSBhIHNpbXBsZSBoeXBvdGhldGljYWwgZGF0YSBzZXQgdG8gaWxsdXN0cmF0ZSBzb21lIGlzc3VlcyB3aGVuIGNvdmFyaWF0ZSByYW5nZXMgZG8gbm90IG1hdGNoIHdlbGwuIFRoZSBkYXRhIHNldCBjb25zaXN0cyBvZiB0d28gdHJlYXRtZW50IGdyb3VwcywgYSBzaW5nbGUgcmVzcG9uc2UgdmFyaWFibGUgKFkpIGFuZCBhIHNpbmdsZSBjb3ZhcmlhdGUgKFgpIFRoaWUgZGF0YSBmaWxlIGlzIFtoZXJlXSguLi9kYXRhL2NvdnJhbmdlLmNzdikKCiMjIyBQcmVsaW1pbmFyaWVzCgpGaXJzdCwgbG9hZCB0aGUgcmVxdWlyZWQgcGFja2FnZXMgKGNhcikKCmBgYHtyIGluY2x1ZGUgPSBGQUxTRSwgcmVzdWx0cyA9ICdoaWRlJywgZXJyb3IgPSBUUlVFfQpzb3VyY2UoIi4uL1IvbGlicmFyaWVzLlIiKSAgI1RoaXMgaXMgdGhlIGNvbW1vbiBsaWJyYXJ5CmxpYnJhcnkocmVnaGVscGVyKQpsaWJyYXJ5KGludGVyYWN0aW9ucykKbGlicmFyeShrYWRlcikKbGlicmFyeShlZmZlY3RzKQpgYGAKCkltcG9ydCBjb3ZyYW5nZSBkYXRhIGZpbGUKCmBgYHtyfQpjb3ZyYW5nZSA8LSByZWFkLmNzdigiLi4vZGF0YS9jb3ZyYW5nZS5jc3YiKQpoZWFkKGNvdnJhbmdlLDEwKQojTWFrZSBncm91cCBhIGZhY3Rvcgpjb3ZyYW5nZSRncm91cDwtZmFjdG9yKGNvdnJhbmdlJGdyb3VwKQpgYGAKCiMjIyBGaXQgZnVsbCBtb2RlbCB3aXRoIGludGVyYWN0aW9uIHRvIGV2YWx1YXRlIGhvbW9nZW5lb3VzIHNsb3BlcwoKQWxsIFNTIHR5cGVzIHByb2R1Y2Ugc2FtZSByZXN1bHQgZm9yIGludGVyYWN0aW9uCgpgYGB7ciB9CmNvdnJhbmdlLmFvdjEgPC0gYW92KHl+Z3JvdXAreCtncm91cCp4LCBkYXRhID0gY292cmFuZ2UpCnBsb3QoY292cmFuZ2UuYW92MSkKYGBgCgpgYGB7ciB9CkFub3ZhKGNvdnJhbmdlLmFvdjEsIHR5cGUgPSAzKQpgYGAKCk5vdCBzdHJvbmcgZXZpZGVuY2UgZm9yIGhldGVyb2dlbm91cyBzbG9wZXMKCiMjIyBSdW4gc2ltcGxlciBtb2RlbAoKYGBge3IgfQpjb3ZyYW5nZS5hb3YyIDwtIGFvdih5fmdyb3VwK3gsIGRhdGEgPSBjb3ZyYW5nZSkKQW5vdmEoY292cmFuZ2UuYW92MiwgdHlwZSA9IDMpCmBgYAoKR2V0IGFkanVzdGVkIG1lYW5zCgpgYGB7ciB9CmFkam1lYW5zIDwtIGVmZmVjdCgiZ3JvdXAiLCBjb3ZyYW5nZS5hb3YyLCBzZSA9IFRSVUUpCnN1bW1hcnkoYWRqbWVhbnMpCmBgYAoKIyMjIFVzZSBIdWl0ZW1hIGFkanVzdG1lbnQKCkluc3RlYWQgb2YgdXNpbmcgcmF3IHggdmFsdWVzIGFzIGNvdmFyaWF0ZXMsIEh1aXRlbWEgc3VnZ2VzdHMgdXNpbmcgdGhlIHgtcmVzaWR1YWxzIGZyb20gZWFjaCBncm91cC4gVGhpcyBpcyBkb25lIGFscmVhZHkgaW4gdGhlIGRhdGEgZmlsZSAoeHJlcyksIGJ1dCBpdCBjYW4gYmUgZG9uZSBieSBmaXR0aW5nIGEgbG0gd2l0aCB4IGFzIHRoZSByZXNwb25zZSBhbmQgZ3JvdXAgYXMgdGhlIHByZWRpY3RvciwgYW5kIHVzaW5nIHRoZSBjYWxjdWxhdGVkIHJlc2lkdWFscy4gV2UnbGwgc2tpcCB0aGUgY29tcGFyaXNvbiBvZiBzbG9wZXMgYW5kIGp1c3QgcnVuIHRoZSBwb29sZWQgc2xvcGVzIG1vZGVsIGFuZCBnZXQgYWRqdXN0ZWQgbWVhbnMKCmBgYHtyIH0KY292cmFuZ2UuYW92MyA8LSBhb3YoeX5ncm91cCt4cmVzLCBkYXRhID0gY292cmFuZ2UpCkFub3ZhKGNvdnJhbmdlLmFvdjMsIHR5cGUgPSAzKQphZGptZWFucyA8LSBlZmZlY3QoImdyb3VwIiwgY292cmFuZ2UuYW92Mywgc2UgPSBUUlVFKQpzdW1tYXJ5KGFkam1lYW5zKQpgYGAKCiMjIyBHZW5lcmF0ZSBncmFwaAoKYGBge3IgaW5jbHVkZSA9IEZBTFNFLCByZXN1bHRzID0gJ2hpZGUnfQpzb3VyY2UoIi4uL1IvYXBwZWFyYW5jZS5SIikgICNUaGlzIGlzIHRoZSBjb21tb24gbGlicmFyeSBvZiBncmFwaGljcyB0d2Vha3MsIGRlZmluaW5nIHRoZSBxayB0aGVtZQpgYGAKCmBgYHtyfQoKZGYxPC1jb3ZyYW5nZSAgIyBDb3B5IGRhdGFmcmFtZSB0byBkZjEgc28gZ2VuZXJpYyBjb2RlIGNhbiBiZSB1c2VkCmFnZ3JlZ2F0ZSh4ID0gZGYxJHgsICAgICAgICAjIFNwZWNpZnkgZGF0YSBjb2x1bW4KICAgICBieSA9IGxpc3QoZGYxJGdyb3VwKSwgICAgICAgIyBTcGVjaWZ5IGdyb3VwIGluZGljYXRvcgogICAgIEZVTiA9IG1lYW4pIApwMTwtZ2dwbG90KGRhdGEgPSBkZjEsYWVzKHggPSB4LHkgPSB5LGdyb3VwID0gZ3JvdXAsIHNoYXBlID0gZ3JvdXAsIGNvbG9yID0gZ3JvdXApKSsKIGdlb21fcG9pbnQoKSsKIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsc2UgPSBGQUxTRSkrCiBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAzLjg3MiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSBsZikrCiBnZW9tX3NlZ21lbnQoeCA9IDIuODAzLHkgPSA2LHhlbmQgPSAyLjgwMyx5ZW5kID0gNywgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDMsICJtbSIpKSxjb2xvciA9IGxjKSsKIGdlb21fc2VnbWVudCh4ID0gNC45NCx5ID0gNix4ZW5kID0gNC45NCx5ZW5kID0gNywgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDMsICJtbSIpKSxjb2xvciA9IGxjKSsKIGxhYnMoeCA9ICJYIiwgeSA9IE5VTEwpKwogc2NhbGVfY29sb3JfZ3JleShlbmQgPSAwLjYpKwogdGhlbWVfcWsoKSsKIHRoZW1lKAogIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogKQpwMjwtZ2dwbG90KGRhdGEgPSBkZjEsYWVzKHggPSB4cmVzLHkgPSB5LGdyb3VwID0gZ3JvdXAsIHNoYXBlID0gZ3JvdXAsIGNvbG9yID0gZ3JvdXApKSsKIGdlb21fcG9pbnQoKSsKIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsc2UgPSBGQUxTRSkrCiBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9IGxmKSsKIGxhYnMoeCA9ICJYIHJlc2lkdWFsIiwgeSA9IE5VTEwpKwogc2NhbGVfY29sb3JfZ3JleShlbmQgPSAwLjYpKwogdGhlbWVfcWsoKSsKIHRoZW1lKAogIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogKQpwMzwtZ2dwbG90KGRhdGEgPSBkZjEsYWVzKHggPSB4LHkgPSB5KSkrCiBnZW9tX3BvaW50KGNvbG9yID0gc2MpKwogZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIixzZSA9IEZBTFNFLCBjb2xvciA9IHNjLGxpbmV0eXBlID0gImRhc2hlZCIpKwogZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgY29sb3IgPSBsYywgbGluZXR5cGUgPSAic29saWQiLCBzZSA9IEZBTFNFLCBzcGFuID0gMikrCiBsYWJzKHggPSAiWCIsIHkgPSBOVUxMKSsKIHNjYWxlX2NvbG9yX2dyZXkoZW5kID0gMC42KSsKIHRoZW1lX3FrKCkrCiB0aGVtZSgKICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICkKcDErcDIrcDMKYGBgCg==