Data Analysis for the Life Sciences

DALS014-Linear Models线性模型03比较(co

2019-08-25  本文已影响0人  backup备份

title: DALS014-Linear Models线性模型03比较(contrast)与交互项
date: 2019-08-19 12:0:00
type: "tags"
tags:


前言

这一部分是《Data Analysis for the life sciences》的第5章线性模型的第3小节。这一部分的主要内容涉及线性回归的比较与交互项。

文献解读

我们会使用一篇文献中的数据集来学习复杂的线性模型,这个数据集包括了蜘蛛不同腿上的不同摩擦系数,具体地说就是,我们要研究腿部的推拉运动是否会产生不同强度的摩擦力。

文献信息如下所示:

Jonas O. Wolff & Stanislav N. Gorb, Radial arrangement of Janus-like setae permits friction control
in spiders⁷³, Scientific Reports, 22 January 2013.

通过这篇文献的摘要我们大致知道这篇文献的主要研究内容是,研究了一种游猎型蜘蛛Cupiennius Salei(蜘蛛目,蜘蛛科)在其远端腿上有毛状附着垫(爪状毛),这个附着垫是由定向分枝的刚毛组成的。作者测量了爪状毛在光滑玻璃上的摩擦力,从而揭示了垫内刚毛排列的功能效应。

文献的Figure1如下所示:

image

Figure1一些有关蜘蛛爪状毛(claw tufts)的电镜照片,这些都是专业知识,我们不用管,我们主要的兴趣在Figure4上,如下所示:

image

Figure4比较了拉(pulling)与推(pushing)这两个动作 ,也就是Figure3中的A图,如下所示:

image

导入数据

作者已经在他的Github上分享的文献的原始实验数据,如下所示:

url <- "https://raw.githubusercontent.com/genomicsclass/dagdata/master/inst/extd\
ata/spider_wolff_gorb_2013.csv"
filename <- "spider_wolff_gorb_2013.csv"
library(downloader)
if (!file.exists(filename)) download(url, filename)
spider <- read.csv(filename, skip=1)

先来大概看一下数据,如下所示:

> table(spider$leg,spider$type)
    
     pull push
  L1   34   34
  L2   15   15
  L3   52   52
  L4   40   40

其中L1~L4是蜘蛛身上不同的腿,现在我们画一个箱线图来看一下这些数据,如下所示:

boxplot(spider$friction ~ spider$type * spider$leg,
col=c("grey90","grey40"), las=2,
main="Comparison of friction coefficients of different leg pairs")
image

从这张图上我们可以直接看出2点信息:

  1. 拉(pulling)比推(pushing)产生的摩擦力更大;
  2. 后腿(也就是L4)产生的拉力(puling friction)最高。

另外,如果仔细看箱线图的话,还会发现,不同组之间的平均值分布不同,这就是组内方差(within-group variance)。对于线性模型来说,有时候组内方差会成为一个问题,因为我们会假设每组的均值会在总体均值附近波动,也就是说误差\varepsilon_{i} 的分布是相同的,也就是说,每组的方差是相同的。如果忽视不同的组的不同方差,那么一些方差比较小的组就会显示过于“保守”(因为方差的总体估计会大于这些组的估计),并且具有较大方差的那些之间的比较置信度会过高。如果这些异常分布与摩擦力的范围有关,那么摩擦力值较大的数据造成的影响也大,因此可以采用log或sqrt转换来对数据进行预处理。

如果不进行数据转换(例如log转换或sqrt转换),那么我们也可以使用其他的统计检验,例如Welch t检验或Satterthwaite approximation(这两种都是t检验的扩展,可以在方差不齐的时候使用),或Wilcoxon秩和检验。但是,在这里,我们为了说明一些问题,我们会采用一个线性模型,这个模型假定不同组的方差相同。

单变量线性模型

先看简单的案例,也就是先研究一个变量,即我们现在只研究L1腿,如下所示:

head(spider)
spider.sub <- spider[spider$leg == "L1",]
head(spider.sub)
fit <- lm(friction ~ type, data=spider.sub)
summary(fit)
(coefs <- coef(fit))

结果如下所示:

 head(spider)
  leg type friction
1  L1 pull     0.90
2  L1 pull     0.91
3  L1 pull     0.86
4  L1 pull     0.85
5  L1 pull     0.80
6  L1 pull     0.87
> spider.sub <- spider[spider$leg == "L1",]
> head(spider.sub)
  leg type friction
1  L1 pull     0.90
2  L1 pull     0.91
3  L1 pull     0.86
4  L1 pull     0.85
5  L1 pull     0.80
6  L1 pull     0.87
> fit <- lm(friction ~ type, data=spider.sub)
> summary(fit)

Call:
lm(formula = friction ~ type, data = spider.sub)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.33147 -0.10735 -0.04941 -0.00147  0.76853 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)  0.92147    0.03827  24.078  < 2e-16
typepush    -0.51412    0.05412  -9.499  5.7e-14
               
(Intercept) ***
typepush    ***
---
Signif. codes:  
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2232 on 66 degrees of freedom
Multiple R-squared:  0.5776,    Adjusted R-squared:  0.5711 
F-statistic: 90.23 on 1 and 66 DF,  p-value: 5.698e-14
> (coefs <- coef(fit))
(Intercept)    typepush 
  0.9214706  -0.5141176 

从上面的结果可以看出,L1这一组(L1这一组中有push,有pull)的均值为0.9214706,拉(pull)与推(push)摩擦力的差值是-0.5141176 ,现在我们在R中再计算一下,看是否相符,如下所示:

s <- split(spider.sub$friction, spider.sub$type)
mean(s[["pull"]])
mean(s[["push"]]) - mean(s[["pull"]])

结果如下所示:

> s <- split(spider.sub$friction, spider.sub$type)
> mean(s[["pull"]])
[1] 0.9214706
> mean(s[["push"]]) - mean(s[["pull"]])
[1] -0.5141176

上面的是常规方法,我们也可以通过设计矩阵来进行计算,如下所示:

X <- model.matrix(~ type, data=spider.sub)
colnames(X)
head(X)
tail(X)

结果如下所示:

> X <- model.matrix(~ type, data=spider.sub)
> colnames(X)
[1] "(Intercept)" "typepush"   
> head(X)
  (Intercept) typepush
1           1        0
2           1        0
3           1        0
4           1        0
5           1        0
6           1        0
> tail(X)
   (Intercept) typepush
63           1        1
64           1        1
65           1        1
66           1        1
67           1        1
68           1        1

现在我们来绘制一个\mathbf{X}矩阵的示意图,其中,黑块表示1,白块表示0,这种方法对于我们理解线性模型比较有用。在这个图形中,y轴表示样本数目(也就是数据的行数),x轴是设计矩阵\mathbf{X}的列。我们使用rafalib包中的imagemat()函数即可,如下所示:

library(rafalib)
imagemat(X, main="Model matrix for linear model with one variable")
image

计算估计系数(examining the estimated coefficients)

下图是由线性模型计算而来的估计系数:

set.seed(1) #same jitter in stripchart
stripchart(split(spider.sub$friction, spider.sub$type), 
           vertical=TRUE, pch=1, method="jitter", las=2, xlim=c(0,3), ylim=c(0,2))
a <- -0.25
lgth <- .1
library(RColorBrewer)
cols <- brewer.pal(3,"Dark2")
abline(h=0)
arrows(1+a,0,1+a,coefs[1],lwd=3,col=cols[1],length=lgth)
abline(h=coefs[1],col=cols[1])
arrows(2+a,coefs[1],2+a,coefs[1]+coefs[2],lwd=3,col=cols[2],length=lgth)
abline(h=coefs[1]+coefs[2],col=cols[2])
legend("right",names(coefs),fill=cols,cex=.75,bg="white")
image

其中,绿色箭头表示截矩(Intercept),其范围是从0到参考组均值的距离(这里的参考组是pull)。橘黄色的箭头表示push组与pull组的差值,在上面图形中,箭头向下,表示负值。小圆圈表示的是每个数据,其中为了避免相同数据的重叠,就在水平上进行了一定程度的波动。

双变量线性模型

再进一步,现在我们研究整个数据集。为了研究不同的腿(L1,L2,L3和L4)的push和pull的差异,我们需要构建一个双变量R公式(R formula),如下所示:

X <- model.matrix(~ type + leg, data=spider)
colnames(X)
head(X)
imagemat(X, main="Model matrix for linear model with two factors")

结果如下所示:

> X <- model.matrix(~ type + leg, data=spider)
> colnames(X)
[1] "(Intercept)" "typepush"    "legL2"       "legL3"       "legL4"      
> head(X)
  (Intercept) typepush legL2 legL3 legL4
1           1        0     0     0     0
2           1        0     0     0     0
3           1        0     0     0     0
4           1        0     0     0     0
5           1        0     0     0     0
6           1        0     0     0     0
image

上面的黑白图是对公式type+leg的简单表示。

从计算结果,以及黑白示意图上我们可以知道:

第1列是截矩(intercept),所有值都是1;

第2列:含有1的是push,从示意图上可以看出来,1是黑色,连续的黑色方块一共是4块,因此一共是4组;

第3列:含有1的是L2;

第4列:含有1的是L3;

第5列:含有1的是L4。

这里没有提到L1是因为L1是leg变量的参考水平。同样的,里面也没有提到pull,因为pull是type变量的参考水平。

如果要计算出相应的系数,需要使用lm()函数,公式为~ type + leg,如下所示:

fitTL <- lm(friction ~ type + leg, data=spider)
summary(fitTL)
(coefs <- coef(fitTL))

结果如下所示:

> fitTL <- lm(friction ~ type + leg, data=spider)
> summary(fitTL)

Call:
lm(formula = friction ~ type + leg, data = spider)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.46392 -0.13441 -0.00525  0.10547  0.69509 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  1.05392    0.02816  37.426  < 2e-16 ***
typepush    -0.77901    0.02482 -31.380  < 2e-16 ***
legL2        0.17192    0.04569   3.763 0.000205 ***
legL3        0.16049    0.03251   4.937 1.37e-06 ***
legL4        0.28134    0.03438   8.183 1.01e-14 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2084 on 277 degrees of freedom
Multiple R-squared:  0.7916,    Adjusted R-squared:  0.7886 
F-statistic:   263 on 4 and 277 DF,  p-value: < 2.2e-16
> (coefs <- coef(fitTL))
(Intercept)    typepush       legL2       legL3       legL4 
  1.0539153  -0.7790071   0.1719216   0.1604921   0.2813382 

R的计算结果中,在coefficient这一部分中含有最小方差估计值。

数学表达式

我们拟合的线性模型可以使用下面的式子表示:
Y_i = \beta_0 + \beta_1 x_{i,1} + \beta_2 x_{i,2} + \beta_3 x_{i,3} + \beta_4 x_{i,4} + \varepsilon_i, i=1,\dots,N
其中,x表示所有的指示变量(indicator variables),在这个案例中指提是不同腿的push与pull。例如对于第3条腿的push来说,就是x_{i,1}x_{i,3}等于1,剩下的等于0。\beta指的是它们表示的效应大小。例如\beta_{0}表示截矩,而\beta_{1}表示pull效应(pull effect),而\beta_{2}一表示L2效应等。上面计算结果里没有直接表明系数,即\beta_{1},但是标明了估计值,例如\hat{\beta_{4}}

我们还可以使用矩阵来计算最小二乘估计,如下所示:

\hat{\boldsymbol{\beta}} = (\mathbf{X}^\top \mathbf{X})^{-1} \mathbf{X}^\top \mathbf{Y}
如下所示:

Y <- spider$friction
X <- model.matrix(~ type + leg, data=spider)
beta.hat <- solve(t(X) %*% X) %*% t(X) %*% Y
t(beta.hat)
coefs

结果如下所示:

> t(beta.hat)
     (Intercept)   typepush     legL2     legL3     legL4
[1,]    1.053915 -0.7790071 0.1719216 0.1604921 0.2813382
> coefs
(Intercept)    typepush       legL2       legL3       legL4 
  1.0539153  -0.7790071   0.1719216   0.1604921   0.2813382 

从上面的结果可以看出来,这个与lm()计算出来的结果一样。

计算估计值系数

现在绘制出上述结果的示意图,如下所示:

spider$group <- factor(paste0(spider$leg, spider$type))
stripchart(split(spider$friction, spider$group), 
           vertical=TRUE, pch=1, method="jitter", las=2, xlim=c(0,11), ylim=c(0,2))
cols <- brewer.pal(5,"Dark2")
abline(h=0)
arrows(1+a,0,1+a,coefs[1],lwd=3,col=cols[1],length=lgth)
abline(h=coefs[1],col=cols[1])
arrows(3+a,coefs[1],3+a,coefs[1]+coefs[3],lwd=3,col=cols[3],length=lgth)
arrows(5+a,coefs[1],5+a,coefs[1]+coefs[4],lwd=3,col=cols[4],length=lgth)
arrows(7+a,coefs[1],7+a,coefs[1]+coefs[5],lwd=3,col=cols[5],length=lgth)
arrows(2+a,coefs[1],2+a,coefs[1]+coefs[2],lwd=3,col=cols[2],length=lgth)
segments(3+a,coefs[1]+coefs[3],4+a,coefs[1]+coefs[3],lwd=3,col=cols[3])
arrows(4+a,coefs[1]+coefs[3],4+a,coefs[1]+coefs[3]+coefs[2],lwd=3,col=cols[2],length=lgth)
segments(5+a,coefs[1]+coefs[4],6+a,coefs[1]+coefs[4],lwd=3,col=cols[4])
arrows(6+a,coefs[1]+coefs[4],6+a,coefs[1]+coefs[4]+coefs[2],lwd=3,col=cols[2],length=lgth)
segments(7+a,coefs[1]+coefs[5],8+a,coefs[1]+coefs[5],lwd=3,col=cols[5])
arrows(8+a,coefs[1]+coefs[5],8+a,coefs[1]+coefs[5]+coefs[2],lwd=3,col=cols[2],length=lgth)
legend("right",names(coefs),fill=cols,cex=.75,bg="white")
image

上图是线性模型的估计值示意图。其中茶绿色(teal-green)箭头表示截矩(intercept),它拟合的是参考组,这里指的是L1的pull。紫色(purple)、粉色(pink),黄绿色(yello-green)表示提其它组与L1的差值。黄色箭头(orange arrow)表示是push和push的差值。

在这个案例中,每组拟合的均值是由拟合的系数推导出来的, 它与我们简单地从8组中计算的均值不太一致。原因是,我们的模型使用了5个系数,而不是8个。我们假设效应是可加的(additive)。但是我们在下文中还会考虑更多的因素来进行拟合,例如考虑这个数据集中的交互因素。

现在看一下简单地计算平均值与线性模型推导出来的平均值,如下所示:

s <- split(spider$friction, spider$group)
mean(s[["L1pull"]])
coefs[1]
mean(s[["L1push"]])
coefs[1] + coefs[2]

计算结果如下所示:

> s <- split(spider$friction, spider$group)
> mean(s[["L1pull"]])
[1] 0.9214706
> coefs[1]
(Intercept) 
   1.053915 
> mean(s[["L1push"]])
[1] 0.4073529
> coefs[1] + coefs[2]
(Intercept) 
  0.2749082 

上面的计算过程是比较push与pull的估计值,其中coefs[2]是每组均值差异的加权平均值。此外,权重(weight)是由每组的样本数量决定的。这里计算的过程非常简单,因为每组的样本数目(pull与push)都相等。如果样本数目不等(例如push和pull不等),那么权重的计算就比较复杂,但是,每组的样本数目,总的样本数目以及系数的数目都会计算出相应唯一的权重。这可能通过(\mathbf{X}^\top \mathbf{X})^{-1} \mathbf{X}^\top计算得到,如下所示:

means <- sapply(s, mean)
##the sample size of push or pull groups for each leg pair
ns <- sapply(s, length)[c(1,3,5,7)]
(w <- ns/sum(ns))
sum(w * (means[c(2,4,6,8)] - means[c(1,3,5,7)]))
coefs[2]
sum(w * (means[c(2,4,6,8)] - means[c(1,3,5,7)]))

结果如下所示:

> (w <- ns/sum(ns))
   L1pull    L2pull    L3pull    L4pull 
0.2411348 0.1063830 0.3687943 0.2836879 
> sum(w * (means[c(2,4,6,8)] - means[c(1,3,5,7)]))
[1] -0.7790071
> coefs[2]
  typepush 
-0.7790071 
> sum(w * (means[c(2,4,6,8)] - means[c(1,3,5,7)]))
[1] -0.7790071

比较系数(Contrasting coefficients)

有的时候,我们可能对模型中单个系数表示的比较结果感兴趣,例如push与pull的差值,也就是上面的coefs[2]。但是,有的时候,由单一的系数无法得到想要的比较结果,但是联合使用几个系数可以进行比较,这就是比较系数(contrast)。为了引入contrast的概念,我们先来看一下coefs这个变量,如下所示:

> coefs
(Intercept)    typepush       legL2       legL3       legL4 
  1.0539153  -0.7790071   0.1719216   0.1604921   0.2813382

这个结果包含截矩的估计值,push与pull的估计效应,L2与L1效应的估计值,L3与L1效应估计值,L4与L1效应的估计值。假设我们想要比较两组数的效应大小,并且其中一组不是L1怎么办?这个解决过程就叫比较(contrast)。

比较(contrast)是对估计效应(estimated coefficient)的联合过计算,即\mathbf{c^\top} \hat{\boldsymbol{\beta}},其中\mathbf{c}是一个列向量,其行数与线性模型系数的数目相同。如果\mathbf{c}中含有1个或多个0,那就表示相应的\hat{\beta}中的估计系数就不参与相应的比较系数(contrast)计算。

如果我们想比较L2和L3,它就相当于在线性模型中比较这两个系数,因为它们都是与L1进行比较的,如下所示:

(\mbox{L3} - \mbox{L1}) - (\mbox{L2} - \mbox{L1}) = \mbox{L3} - \mbox{L2 }
对这两种进行比较的一个简单途径就是使用constrast包中的contrast()函数。我们只需要指定要比较的两组名称即可,现在我们来比较一下pull或push类型,如下所示:

library(contrast) #Available from CRAN
L3vsL2 <- contrast(fitTL,list(leg="L3",type="pull"),list(leg="L2",type="pull"))
L3vsL2

结果如下所示:

> L3vsL2
lm model parameter contrast

    Contrast       S.E.      Lower      Upper     t  df Pr(>|t|)
 -0.01142949 0.04319685 -0.0964653 0.07360632 -0.26 277   0.7915

第1列是Contrast,它表示的是L3与L2的估计值。

我们可以证明,系数的线性组合的最小二乘估计是这些估计的相同线性组合。因此,效应大小估计值(effect size estimate)就是两者之间的差值。使用contrast()函数进行比较的比较向量,被储备成为一个称为X变量中,如下所示:

coefs[4] - coefs[3]
(cT <- L3vsL2$X)
cT %*% coefs

计算结果如下所示:

> coefs[4] - coefs[3]
      legL3 
-0.01142949 
> (cT <- L3vsL2$X)
  (Intercept) typepush legL2 legL3 legL4
1           0        0    -1     1     0
attr(,"assign")
[1] 0 1 2 2 2
attr(,"contrasts")
attr(,"contrasts")$type
[1] "contr.treatment"

attr(,"contrasts")$leg
[1] "contr.treatment"

> cT %*% coefs
         [,1]
1 -0.01142949

计算结果里面还有t检验与标准误,我们以前提到过,t检验是一个估计值,它的除数就标准误。比较估计值的标准误是由比较向量\mathbf{c}乘以估计的协方差矩阵\hat{\Sigma}的任意一边得到的,我们对var\hat{\beta}的估计值如下所示:
\sqrt{\mathbf{c^\top} \hat{\boldsymbol{\Sigma}} \mathbf{c}}

系数的协方差为:
\boldsymbol{\Sigma} = \sigma^2 (\mathbf{X}^\top \mathbf{X})^{-1}
我们使用样本估计值\hat{\sigma}^2来估计{\sigma}^2,如下所示:

Sigma.hat <- sum(fitTL$residuals^2)/(nrow(X) - ncol(X)) * solve(t(X) %*% X)
signif(Sigma.hat, 2)
sqrt(cT %*% Sigma.hat %*% t(cT))
L3vsL2$SE

计算结果如下所示:

> Sigma.hat <- sum(fitTL$residuals^2)/(nrow(X) - ncol(X)) * solve(t(X) %*% X)
> signif(Sigma.hat, 2)
            (Intercept) typepush    legL2    legL3    legL4
(Intercept)     0.00079 -3.1e-04 -0.00064 -0.00064 -0.00064
typepush       -0.00031  6.2e-04  0.00000  0.00000  0.00000
legL2          -0.00064 -6.4e-20  0.00210  0.00064  0.00064
legL3          -0.00064 -6.4e-20  0.00064  0.00110  0.00064
legL4          -0.00064 -1.2e-19  0.00064  0.00064  0.00120
> sqrt(cT %*% Sigma.hat %*% t(cT))
           1
1 0.04319685
> L3vsL2$SE
[1] 0.04319685

如果我们选择参数type="push",那么我们就会获得与L3和L2比较的一样的结果。其原因就是,在差值的两侧都添加了typepush效应(这一句不太理解)我们可以取消它,如下所示:

L3vsL2.equiv <- contrast(fitTL,list(leg="L3",type="push"),list(leg="L2",type="push"))
L3vsL2.equiv$X

运行结果如下所示:

> L3vsL2.equiv <- contrast(fitTL,list(leg="L3",type="push"),list(leg="L2",type="push"))
> L3vsL2.equiv$X
  (Intercept) typepush legL2 legL3 legL4
1           0        0    -1     1     0
attr(,"assign")
[1] 0 1 2 2 2
attr(,"contrasts")
attr(,"contrasts")$type
[1] "contr.treatment"

attr(,"contrasts")$leg
[1] "contr.treatment"

交互项(interaction terms)

在前面的线性模型案例中,我们假设pull与push的效应对于所有的腿(leg)都是相同的(也就是说橘黄色的箭头是一样的),但是从我们最终计算的结果来看,并不能很好的捕获数据的趋势,换句话讲,就是简单与每组的平均值并不完全一致。例如L1组,push与pull估计系数太大,而L3组,push与pull又太小。

此时,我们引入交互项(interaction terms),这个引入的系数可以解决不同组中push与pull差值过大的问题。由于我们在模型中已经有了push与pull项,因此我们只需要再添加三个项就能够找到leg-piar特异性push和pull的差异。在下面我们会向模型的设计矩阵中添加交互项(interaction terms),其方法是将代表现有项的设计矩阵列相乘。

我们可以在typeleg之间构建一个交互项,即type:leg,其中的冒号:表示两个变量存在交互作用,另外一种相同的做法就是~type*leg,这两种写法都是主要研究typeleg之间的交互作用,而不研究其他变量之间的交互作用,如下所示:

url <- "https://raw.githubusercontent.com/genomicsclass/dagdata/master/inst/extd\
ata/spider_wolff_gorb_2013.csv"
filename <- "spider_wolff_gorb_2013.csv"
library(downloader)
if (!file.exists(filename)) download(url, filename)
spider <- read.csv(filename, skip=1)
X <- model.matrix(~ type + leg + type:leg, data=spider)
colnames(X)
X <- model.matrix(~type*leg, data=spider)
colnames(X)
head(X)
library(rafalib)
imagemat(X, main="Model matrix for linear model with interactions")

计算结果如下所示:

> X <- model.matrix(~ type + leg + type:leg, data=spider)
> colnames(X)
[1] "(Intercept)"    "typepush"       "legL2"          "legL3"         
[5] "legL4"          "typepush:legL2" "typepush:legL3" "typepush:legL4"
> X <- model.matrix(~type*leg, data=spider)
> colnames(X)
[1] "(Intercept)"    "typepush"       "legL2"          "legL3"         
[5] "legL4"          "typepush:legL2" "typepush:legL3" "typepush:legL4"
> head(X)
  (Intercept) typepush legL2 legL3 legL4 typepush:legL2 typepush:legL3
1           1        0     0     0     0              0              0
2           1        0     0     0     0              0              0
3           1        0     0     0     0              0              0
4           1        0     0     0     0              0              0
5           1        0     0     0     0              0              0
6           1        0     0     0     0              0              0
  typepush:legL4
1              0
2              0
3              0
4              0
5              0
6              0
image

其中,第6到8列表示的是:typepush:legL2typepush:legL3typepush:legL4,也就是说,它们是由第2列的typepush和第3到5列的legL2legL3legL4产生的。我们看最后1列,即typepush:legL4列,这是另外的一个系数,即\beta_{push,L4},此系数表示push与L4共同作用的样本。这就可能对L4-push这一组样本的均值的差异进行解释,例如当我们通过估计的截距、估计的typepush系数,估计的L4系数LegL4来对数据进行预测时产生偏差(例如数据点不在估计的直线上),当我们考虑了交互作用后,其结果如下所示:

fitX <- lm(friction ~ type + leg + type:leg, data=spider)
summary(fitX)
coefs <- coef(fitX)
coefs

结果如下所示:

> fitX <- lm(friction ~ type + leg + type:leg, data=spider)
> summary(fitX)

Call:
lm(formula = friction ~ type + leg + type:leg, data = spider)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.46385 -0.10735 -0.01111  0.07848  0.76853 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)     0.92147    0.03266  28.215  < 2e-16 ***
typepush       -0.51412    0.04619 -11.131  < 2e-16 ***
legL2           0.22386    0.05903   3.792 0.000184 ***
legL3           0.35238    0.04200   8.390 2.62e-15 ***
legL4           0.47928    0.04442  10.789  < 2e-16 ***
typepush:legL2 -0.10388    0.08348  -1.244 0.214409    
typepush:legL3 -0.38377    0.05940  -6.461 4.73e-10 ***
typepush:legL4 -0.39588    0.06282  -6.302 1.17e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1904 on 274 degrees of freedom
Multiple R-squared:  0.8279,    Adjusted R-squared:  0.8235 
F-statistic: 188.3 on 7 and 274 DF,  p-value: < 2.2e-16
> coefs
   (Intercept)       typepush          legL2          legL3          legL4 
     0.9214706     -0.5141176      0.2238627      0.3523756      0.4792794 
typepush:legL2 typepush:legL3 typepush:legL4 
    -0.1038824     -0.3837670     -0.3958824 

计算估计系数

现在我们先画一下上面的计算结果,如下所示:

library(RColorBrewer)
spider$group <- factor(paste0(spider$leg, spider$type))
stripchart(split(spider$friction, spider$group), 
           vertical=TRUE, pch=1, method="jitter", las=2, xlim=c(0,11), ylim=c(0,2))
cols <- brewer.pal(8,"Dark2")
abline(h=0)
arrows(1+a,0,1+a,coefs[1],lwd=3,col=cols[1],length=lgth)
abline(h=coefs[1],col=cols[1])
arrows(2+a,coefs[1],2+a,coefs[1]+coefs[2],lwd=3,col=cols[2],length=lgth)
arrows(3+a,coefs[1],3+a,coefs[1]+coefs[3],lwd=3,col=cols[3],length=lgth)
arrows(5+a,coefs[1],5+a,coefs[1]+coefs[4],lwd=3,col=cols[4],length=lgth)
arrows(7+a,coefs[1],7+a,coefs[1]+coefs[5],lwd=3,col=cols[5],length=lgth)
#now the interactions:
segments(3+a,coefs[1]+coefs[3],4+a,coefs[1]+coefs[3],lwd=3,col=cols[3])
arrows(4+a,coefs[1]+coefs[3],4+a,coefs[1]+coefs[3]+coefs[2],lwd=3,col=cols[2],length=lgth)
arrows(4+a,coefs[1]+coefs[2]+coefs[3],4+a,coefs[1]+coefs[2]+coefs[3]+coefs[6],lwd=3,col=cols[6],length=lgth)
segments(5+a,coefs[1]+coefs[4],6+a,coefs[1]+coefs[4],lwd=3,col=cols[4])
arrows(6+a,coefs[1]+coefs[4],6+a,coefs[1]+coefs[4]+coefs[2],lwd=3,col=cols[2],length=lgth)
arrows(6+a,coefs[1]+coefs[4]+coefs[2],6+a,coefs[1]+coefs[4]+coefs[2]+coefs[7],lwd=3,col=cols[7],length=lgth)
segments(7+a,coefs[1]+coefs[5],8+a,coefs[1]+coefs[5],lwd=3,col=cols[5])
arrows(8+a,coefs[1]+coefs[5],8+a,coefs[1]+coefs[5]+coefs[2],lwd=3,col=cols[2],length=lgth)
arrows(8+a,coefs[1]+coefs[5]+coefs[2],8+a,coefs[1]+coefs[5]+coefs[2]+coefs[8],lwd=3,col=cols[8],length=lgth)
legend("right",names(coefs),fill=cols,cex=.75,bg="white")
image

估计的交互作用系数就能反映出在对push和pull进行比较时,leg-pair-specific导致的差值不同。上图的橘黄色简单表示的是与L1相比,push和pull的差值估计。如果估计的交互系数过大,那么push与pull差值的均值就与参考组相比(也就是L1组中push和pull差值的均值),非常不同。

比较(contrast)

在一些简单案例中,我们会使用contrast包来进行比较,混合计算估计系数。例如我们知道L2样本的push与pull效应。我们可以从上面箭图中看出来(也就是黄色箭头加上橘黄色简单),我们也可以在contrast()函数中指定要比较哪两组,如下所示:

library(contrast) ##Available from CRAN
L2push.vs.pull <- contrast(fitX,
list(leg="L2", type = "push"),
list(leg="L2", type = "pull"))
L2push.vs.pull
coefs[2] + coefs[6] ##we know this is also orange + yellow arrow

计算结果如下所示:

> L2push.vs.pull
lm model parameter contrast

 Contrast      S.E.      Lower      Upper     t  df Pr(>|t|)
   -0.618 0.0695372 -0.7548951 -0.4811049 -8.89 274        0
> coefs[2] + coefs[6] ##we know this is also orange + yellow arrow
typepush 
  -0.618 

差值的差异(Differences of differences)

push与pull在L2中的差异和push与pull在L1中的差异是不同的,为什么会不同的,我们可以使用模型中的typepush:legL2估计系数,也就是上图中的黄色箭头。这个系数的p值是否等于0,可以从上面的summary(fitX)函数来查看。同样的,我们也可以看出来L3与L1中差值(push和pull的差值)的差异和L4与L1的差值。假设我们想知道push与pull在L3中的差异与L2中的差值是否相同。在上面的图形中,我们可以看到,除了L1之外的其他腿的push和pull效应就是typepush箭头加上该组的交互作用项。

如果我们想比较两个非参考组,那么数学公式如下所示:
(\mbox{typepush} + \mbox{typepush:legL3}) - (\mbox{typepush} + \mbox{typepush:legL2})
可以简写为:
= \mbox{typepush:legL3} - \mbox{typepush:legL2}
在这里我们无法使用contrast()函数直接比较,但是我们可以使用glht()函数进行比较(这个函数的全称是general liner hypothesis test),这个函数在multcomp包中。为了使用glht()这个函数,我们需要构建一个矩阵,这个矩阵只有一行,其中-1表示typepush:legL2系数,其中+1表示typepush:legL3系数。我们将这个矩阵加入到linfct()函数中(这个函数是linear function的缩写),当成linfct()的参数,计算后,我们会获得一个有关估计交互系数比较的表,如下所示:

library(multcomp) ##Available from CRAN
C <- matrix(c(0,0,0,0,0,-1,1,0), 1)
C
L3vsL2interaction <- glht(fitX, linfct=C)
summary(L3vsL2interaction)

计算结果如下所示:

> C
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    0    0    0    0   -1    1    0
> L3vsL2interaction <- glht(fitX, linfct=C)
> summary(L3vsL2interaction)

     Simultaneous Tests for General Linear Hypotheses

Fit: lm(formula = friction ~ type + leg + type:leg, data = spider)

Linear Hypotheses:
       Estimate Std. Error t value Pr(>|t|)    
1 == 0 -0.27988    0.07893  -3.546  0.00046 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Adjusted p values reported -- single-step method)
上一篇下一篇

猜你喜欢

热点阅读