Мы рассмотрим

  • Линейные модели c непрерывными и дискретными предикторами
  • Взаимодействие дискретных и непрерывных предикторов

Геометрическая интерпретация коэффициентов регрессии

Но ведь может быть еще и так

  • Как все эти изменения закодировать в уравнении линейной модели?

Похожий интерсепт, похожий угол наклона

Если зависимости для обеих групп выглядят одинаково, то мы можем пользоваться общей линейной регрессией, не учитывать группу

\(Y = b_0 + b_1X\)

Разный интерсепт, похожий угол наклона

\(Y = b_0 + b_1X + b_2 Group2\)

\(Group2 = 1\) если наблюдение из группы 2, и \(Group2 = 0\) в остальных случаях

Уравнение для группы 1: \(Y = b_0 + b_1X\)

Уравнение для группы 2: \(Y = (b_0 + b_2) + b_1X\)

Похожий интерсепт, разный угол наклона

\(Y = b_0 + b_1X + b_2X Group2\)

\(Group2 = 1\) если наблюдение из группы 2, и \(Group2 = 0\) в остальных случаях

Уравнение для группы 1: \(Y = b_0 + b_1X\)

Уравнение для группы 2: \(Y = b_0 + (b_1 + b_2)X\)

Разный интерсепт и разный угол наклона

\(Y = b_0 + b_1X + b_2 Group2 + b_3X Group2\)

\(Group2 = 1\) если наблюдение из группы 2, и \(Group2 = 0\) в остальных случаях

Уравнение для группы 1: \(Y = b_0 + b_1X\)

Уравнение для группы 2: \(Y = (b_0 + b_2) + (b_1 + b_3)X\)

Физический смысл взаимодействия факторов

Не называйте взаимодействие факторов “корреляцией” или “связью”!

Взаимодействие факторов означает, что для разных значений одного из факторов зависимость от другого фактора выглядит по-разному.

Т.е. в данном случае можно сказать: “Для группы 1 и группы 2 зависимость Y от Х выглядит по-разному”

Если у дискретного предиктора становится больше уровней…

\[y_i = \beta_0 + \beta_1x_1 + \big(\beta_2x_2 + ... + \beta_l x_l\big) + \big(\beta_{l+1}x_{l+1} + ... + \beta_m x_m\big) \cdot x_1 + \epsilon_i\]

В случае, если у дискретного фактора \(k\) градаций, уравнение полной модели будет включать несколько групп коэффициентов:

  • \(\beta_0\) — значение свободного члена для базового уровня дискретного фактора
  • \(\beta_1\) — коэффициент угла наклона для базового уровня дискретного фактора

Поправки для свободного члена:

  • \(\beta_2, ..., \beta_l\) — коррекция свободного члена для других уровней (всего их \(p = k - 1\))

Поправки для угла наклона:

  • \(\beta_{l+1}, ..., \beta_m\) — коррекция коэффициентов угла наклона для других уровней (всего их \(p = k - 1\))

Пример: Пуромицин

Пуромицин - антибиотик пуринового ряда, ингибитор синтеза белков. Эти данные — о том, как меняется активность фермента галактозил трансферазы под воздействием пуромицина (Treloar 1974). Измеряли скорость реакции в зависимости от концентрации субстрата на мембранах аппарата Гольджи из богатых мембранами фракций из печени крыс.

  • conc — концентрация пуромицина
  • rate — скорость химической реакции
  • state — индикатор того, обработаны ли клетки пуромицином
library(readxl)
Puromycin <- read_excel("data/Puromycin.xlsx")
head(Puromycin)
## # A tibble: 6 x 3
##    conc  rate state  
##   <dbl> <dbl> <chr>  
## 1  0.02    76 treated
## 2  0.02    47 treated
## 3  0.06    97 treated
## 4  0.06   107 treated
## 5  0.11   123 treated
## 6  0.11   139 treated

Знакомимся с данными

sapply(Puromycin, class)
##        conc        rate       state 
##   "numeric"   "numeric" "character"
colSums(is.na(Puromycin))
##  conc  rate state 
##     0     0     0
nrow(Puromycin)
## [1] 23

Знакомимся с данными

table(Puromycin$state, Puromycin$conc)
##            
##             0.02 0.06 0.11 0.22 0.56 1.1
##   treated      2    2    2    2    2   2
##   untreated    2    2    2    2    2   1
library(ggplot2)
ggplot(Puromycin, aes(x = state, y = conc)) + geom_boxplot()

Задание

Постройте график зависимости скорости химической реакции от концентрации

Решение

На самом деле, зависимость скорости химической реакции от концентрации нелинейна, но мы попробуем использовать трансформацию

library(ggplot2)
ggplot(Puromycin, aes(x = conc, y = rate, colour = state)) + 
  geom_point()
ggplot(Puromycin, aes(x = log(conc), y = rate, colour = state)) + 
  geom_point()

Запись формулы линейной модели со взаимодействием в R

Response ~ Continuous + Categorical + Continuous : Categorical (полная запись)

Response ~ Continuous * Categorical(сокращенная запись)

Continuous : Categorical — Кодовое обозначение взаимодействия. Добавление взаимодействия непрерывного и дискретного факторов в модель означает, что возможен разный угол наклона прямых для разных групп.

Подберем

Puromycin$lc <- log(Puromycin$conc)
M1 <- lm(rate ~ lc + state + lc:state, data = Puromycin)
# M1 <- lm(rate ~ lc * state, data = Puromycin) # То же самое
summary(M1)
## 
## Call:
## lm(formula = rate ~ lc + state + lc:state, data = Puromycin)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -17.02  -6.38  -1.00   7.62  13.32 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         209.19       4.45   46.97  < 2e-16 ***
## lc                   37.11       1.97   18.86  9.2e-14 ***
## stateuntreated      -44.61       6.81   -6.55  2.9e-06 ***
## lc:stateuntreated   -10.13       2.94   -3.45   0.0027 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 9.15 on 19 degrees of freedom
## Multiple R-squared:  0.968,  Adjusted R-squared:  0.963 
## F-statistic:  191 on 3 and 19 DF,  p-value: 2.27e-14
  • Взаимодействие достоверно!

Проверяем выполнение условий применимости

Решение

# Данные для графиков остатков
M1_diag <- fortify(M1)

1) График расстояния Кука

ggplot(M1_diag, aes(x = 1:nrow(M1_diag), y = .cooksd)) +
  geom_bar(stat = "identity")

Решение

2) График остатков от предсказанных значений

gg_resid <- ggplot(data = M1_diag, aes(x = .fitted, y = .stdresid)) +
  geom_point() + geom_hline(yintercept = 0)
grid.arrange(gg_resid, gg_resid + geom_smooth(),
             gg_resid + geom_smooth(method = "lm"), nrow = 1)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Решение

3) Графики остатков от предикторов в модели и не в модели

library(gridExtra)
grid.arrange(gg_resid + aes(x = lc), 
             ggplot(M1_diag, aes(x = state, y = .stdresid)) + geom_boxplot(), 
             nrow = 1)

Решение

4) Квантильный график остатков

library(car)
qqPlot(M1)

## [1]  2 10

Рисуем график предсказаний

Что не так с этим графиком? Это наша модель?

ggplot(Puromycin, aes(x = lc, y = rate, colour = state)) + 
  geom_point() + 
  geom_smooth(method = "lm")

  • Это не наша модель — здесь разный угол наклона, а у нашей модели график должен быть другой, с одинаковым углом наклона. (По умолчанию ggplot рисует отдельные регрессии для каждого сабсета)

Задание

Постройте график предсказаний модели по этим данным

Данные для графика

library(plyr)
NewData <- ddply(
  Puromycin, .variables = .(state), summarise, 
  lc = seq(min(lc), max(lc), length = 100))

# предсказанные значения
Predictions <- predict(M1, newdata = NewData, se.fit = TRUE)
NewData$fit <- Predictions$fit

# стандартные ошибки
NewData$SE <- Predictions$se.fit

# доверительный интервал
NewData$upr <- NewData$fit + 1.96 * NewData$SE
NewData$lwr <- NewData$fit - 1.96 * NewData$SE

# Обратная трансформация предиктора
NewData$conc <- exp(NewData$lc)

Рисуем график предсказаний (Вторая попытка)

ggplot(NewData, aes(x = conc, y = fit)) + 
  geom_ribbon(alpha = 0.2, aes(ymin = lwr, ymax = upr, group = state)) +
  geom_line(aes(colour = state)) +
  geom_point(data = Puromycin, aes(x = conc, y = rate, colour = state))

Задание

Запишите уравнение этой модели и уравнения для каждой группы

coef(M1)
##       (Intercept)                lc    stateuntreated 
##             209.2              37.1             -44.6 
## lc:stateuntreated 
##             -10.1

Решение

\(rate = 209.2 + 37.1 * lc - 44.6 * stateuntreated - 10.1 * lc * stateuntreated\)

\(stateuntreated = 1\) если \(state = untreated\) и ноль в остальных случаях

Уравнение для treated: \(rate = 209.2 + 37.1 * lc\)

Уравнение для untreated: \(rate = (209.2- 44.6) + (37.1 - 10.1) * lc\),
то есть \(rate = 164.6 + 27 * lc\)

Тестируем гомогенность углов наклона

Это делается как обычно при выборе моделей: при помощи anova() или drop1()

M2 <- lm(rate ~ lc + state, data = Puromycin)

# anova(M1, M2, test="F")
drop1(M1, test = "F")
## Single term deletions
## 
## Model:
## rate ~ lc + state + lc:state
##          Df Sum of Sq  RSS AIC F value Pr(>F)   
## <none>                1591 105                  
## lc:state  1       996 2587 115    11.9 0.0027 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  • Если убрать взаимодействие, то модель становится значительно хуже. Поэтому взаимодействие сохраняем

Представляем результаты в виде таблицы

Вариант 1. Последовательное тестирование (SS type I)

Факторы тестируются в порядке включения в модель. Результат тестирования зависит от порядка включения

anova(M1)
## Analysis of Variance Table
## 
## Response: rate
##           Df Sum Sq Mean Sq F value  Pr(>F)    
## lc         1  43455   43455   518.9 3.0e-15 ***
## state      1   3623    3623    43.3 2.7e-06 ***
## lc:state   1    996     996    11.9  0.0027 ** 
## Residuals 19   1591      84                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
M3 <- lm(rate ~ state + lc + state:lc, data = Puromycin)
anova(M3)
## Analysis of Variance Table
## 
## Response: rate
##           Df Sum Sq Mean Sq F value  Pr(>F)    
## state      1   5464    5464    65.2 1.5e-07 ***
## lc         1  41614   41614   496.9 4.4e-15 ***
## state:lc   1    996     996    11.9  0.0027 ** 
## Residuals 19   1591      84                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Представляем результаты в виде таблицы

Вариант 2. Иерархическое тестирование (SS type III)

Каждый из факторов по отношению к модели только без него, но со всеми остальными. Нужно, если много факторов и выборки разного размера. Тогда результат не будет зависеть от порядка включения факторов в модель.

# library(car)
Anova(M1, type = 3) 
## Anova Table (Type III tests)
## 
## Response: rate
##             Sum Sq Df F value  Pr(>F)    
## (Intercept) 184797  1  2206.5 < 2e-16 ***
## lc           29784  1   355.6 9.2e-14 ***
## state         3592  1    42.9 2.9e-06 ***
## lc:state       996  1    11.9  0.0027 ** 
## Residuals     1591 19                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Anova(M3, type = 3) # сравните

Модель со взаимодействием на примере данных о весе новорожденных

Вес новорожденных и курение

Как вес новорожденных зависит от возраста матери и того, курит ли она

  • age — возраст матери
  • lwt — вес матери до беременности
  • race — раса (1-белые, 2-черные, 3-другие)
  • smoke — курение во время беременности (1-да,2-нет)
  • ptl — число предыдущих преждевременных родов
  • ht — гипертензия
  • ui — гипертонус матки
  • ftv — число визитов к врачу в последний триместр
  • bwt — вес новорожденного, г
wt <- read.table("data/birthwt.csv", header = TRUE, sep = ";")

Задание

  • Исследуйте данные о весе новорожденных
  • Постройте модель зависимости веса новорожденных от возраста матери и взаимодействия
  • Проверьте условия применимости этой модели
  • Упростите модель, если это возможно
  • Напишите общее уравнение и отдельные уравнения модели
  • Постройте график предсказаний модели

Решение

str(wt)
## 'data.frame':    189 obs. of  9 variables:
##  $ age  : int  19 33 20 21 18 21 22 17 29 26 ...
##  $ lwt  : int  182 155 105 108 107 124 118 103 123 113 ...
##  $ race : int  2 3 1 1 1 3 1 3 1 1 ...
##  $ smoke: int  0 0 1 1 1 0 0 0 1 1 ...
##  $ ptl  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ ht   : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ ui   : int  1 0 0 1 1 0 0 0 0 0 ...
##  $ ftv  : int  0 3 1 2 0 0 1 1 1 0 ...
##  $ bwt  : int  2523 2551 2557 2594 2600 2622 2637 2637 2663 2665 ...
colSums(is.na(wt))
##   age   lwt  race smoke   ptl    ht    ui   ftv   bwt 
##     0     0     0     0     0     0     0     0     0
table(wt$smoke, wt$age)
##    
##     14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
##   0  2  3  5  7  3  8 10  7  8  9 10 12  3  2  5  4  5  2  4  2  0  1
##   1  1  0  2  5  7  8  8  5  5  4  3  3  5  1  4  3  2  3  2  1  1  1
##    
##     36 45
##   0  2  1
##   1  0  0
table(wt$smoke, wt$race)
##    
##      1  2  3
##   0 44 16 55
##   1 52 10 12
table(wt$smoke, wt$ui)
##    
##       0   1
##   0 100  15
##   1  61  13

Решение

wt$race <- factor(wt$race)
wt$smoke <- factor(wt$smoke)
wt$ptl <- factor(wt$ptl)
wt$ht <- factor(wt$ht)
wt$ui <- factor(wt$ui)
wt$ftv <- factor(wt$ftv)

Решение

gg_dot <- ggplot(wt, aes(y = 1:nrow(wt))) + geom_point()
gg_dot + aes(x = age)
gg_dot + aes(x = lwt)
gg_dot + aes(x = bwt)

Решение

Проверка на колинеарность

wt_mod_1 <- lm(bwt ~ age + smoke, data = wt)
vif(wt_mod_1)
##   age smoke 
##     1     1
  • Колинеарности нет

Решение

Проверка на гомогенность углов наклона

Подберем полную модель.

wt_mod_2 <- lm(bwt ~ age * smoke, data = wt)
drop1(wt_mod_2, test = "F")
## Single term deletions
## 
## Model:
## bwt ~ age * smoke
##           Df Sum of Sq      RSS  AIC F value Pr(>F)  
## <none>                 93062605 2485                 
## age:smoke  1   2609683 95672288 2488    5.19  0.024 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  • От исключения взаимодействия модель становится значительно хуже. Оставляем

Решение

# Данные для графиков остатков
wt_mod_2_diag <- fortify(wt_mod_2)
wt_mod_2_diag <- data.frame(
  wt_mod_2_diag, 
  wt[, c("lwt", "race", "smoke", "ptl", "ht", "ui", "ftv")])

1) График расстояния Кука

ggplot(wt_mod_2_diag, aes(x = 1:nrow(wt_mod_2_diag), y = .cooksd)) +
  geom_bar(stat = "identity")

Решение

2) График остатков от предсказанных значений

gg_resid <- ggplot(data = wt_mod_2_diag, aes(x = .fitted, y = .stdresid)) +
  geom_point() + geom_hline(yintercept = 0)
gg_resid

Решение

3) Графики остатков от предикторов в модели и не в модели

library(gridExtra)
grid.arrange(gg_resid + aes(x = age), 
             gg_resid + aes(x = lwt), 
             nrow = 1)

Решение

gg_box <- ggplot(data = wt_mod_2_diag, aes(x = smoke, y = .stdresid)) +
  geom_boxplot() + geom_hline(yintercept = 0)

grid.arrange(gg_box + aes(x = smoke), 
             gg_box + aes(x = ftv),
             gg_box + aes(x = race),
             gg_box + aes(x = ht),
             gg_box + aes(x = ui),
             nrow = 2)

Решение

4) Квантильный график остатков

qqPlot(wt_mod_2)

## [1] 131 132

Проверяем значимость коэффициентов

Подумайте, что означают эти коэффициенты

summary(wt_mod_2)
## 
## Call:
## lm(formula = bwt ~ age * smoke, data = wt)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -2189.3  -458.5    51.5   527.3  1521.4 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   2406.1      292.2    8.23  3.2e-14 ***
## age             27.7       12.1    2.28    0.024 *  
## smoke1         798.2      484.3    1.65    0.101    
## age:smoke1     -46.6       20.4   -2.28    0.024 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 709 on 185 degrees of freedom
## Multiple R-squared:  0.0691, Adjusted R-squared:  0.054 
## F-statistic: 4.58 on 3 and 185 DF,  p-value: 0.00407

Записываем уравнение модели

coef(wt_mod_2)
## (Intercept)         age      smoke1  age:smoke1 
##      2406.1        27.7       798.2       -46.6

Общее уравнение:

bwt = 2406.06 + 27.73age + 798.17smoke1 - 46.57age:smoke1

  • Для некурящих: \(N = 2406.06 + 27.73 * age\)
  • Для курящих: \(N = 3204.23 - -18.84 * age\)

Таблица дисперсионного анализа

Anova(wt_mod_2, type = 3)
## Anova Table (Type III tests)
## 
## Response: bwt
##               Sum Sq  Df F value  Pr(>F)    
## (Intercept) 34110331   1   67.81 3.2e-14 ***
## age          2620946   1    5.21   0.024 *  
## smoke        1366143   1    2.72   0.101    
## age:smoke    2609683   1    5.19   0.024 *  
## Residuals   93062605 185                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Сложные модели лучше по возможности изображать в виде графика

Данные для графика

library(plyr)
# Диапазон возрастов разный для курящих и некурящих, поэтому
NewData <- ddply(
  .data = wt, .variables = .(smoke), .fun = summarise,
  age = seq(min(age), max(age), length = 100))

# предсказанные значения
Predictions <- predict(wt_mod_2, newdata = NewData, se.fit = TRUE)
NewData$fit <- Predictions$fit
# стандартные ошибки
NewData$SE <- Predictions$se.fit
# доверительный интервал
NewData$upr <- NewData$fit + 1.96 * NewData$SE
NewData$lwr <- NewData$fit - 1.96 * NewData$SE

Задание

Постройте график предсказаний модели

Рисуем график предсказаний (Вторая попытка)

ggplot(NewData, aes(x = age, y = fit)) +
  geom_ribbon(alpha = 0.2, aes(ymin = lwr, ymax = upr, group = smoke)) +
  geom_line(aes(colour = smoke))

На графике предсказаний можно показать исходные значения

ggplot(NewData, aes(x = age, y = fit)) +
  geom_ribbon(alpha = 0.2, aes(ymin = lwr, ymax = upr, group = smoke)) +
  geom_line(aes(colour = smoke)) +
  geom_point(data = wt, aes(x = age, y = bwt, colour = smoke))

Take home messages

  • У дискретных и непрерывных факторов могут быть взаимодействия, поэтому анализ нужно начинать с более полной модели (чтобы можно было протестировать и исключить недостоверные взаимодействия)

Что почитать

  • Must read paper! Zuur, A.F. and Ieno, E.N., 2016. A protocol for conducting and presenting results of regression‐type analyses. Methods in Ecology and Evolution, 7(6), pp.636-645.

  • Кабаков Р.И. R в действии. Анализ и визуализация данных на языке R. М.: ДМК Пресс, 2014
  • Zuur, A., Ieno, E.N. and Smith, G.M., 2007. Analyzing ecological data. Springer Science & Business Media.
  • Quinn G.P., Keough M.J. 2002. Experimental design and data analysis for biologists
  • Logan M. 2010. Biostatistical Design and Analysis Using R. A Practical Guide