- Линейные модели 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\) градаций, уравнение полной модели будет включать несколько групп коэффициентов:
Поправки для свободного члена:
Поправки для угла наклона:
Пуромицин - антибиотик пуринового ряда, ингибитор синтеза белков. Эти данные — о том, как меняется активность фермента галактозил трансферазы под воздействием пуромицина (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()
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)
ggplot(M1_diag, aes(x = 1:nrow(M1_diag), y = .cooksd)) + geom_bar(stat = "identity")
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'
library(gridExtra) grid.arrange(gg_resid + aes(x = lc), ggplot(M1_diag, aes(x = state, y = .stdresid)) + geom_boxplot(), nrow = 1)
library(car) qqPlot(M1)
## [1] 2 10
Что не так с этим графиком? Это наша модель?
ggplot(Puromycin, aes(x = lc, y = rate, colour = state)) + geom_point() + geom_smooth(method = "lm")
Постройте график предсказаний модели по этим данным
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
Факторы тестируются в порядке включения в модель. Результат тестирования зависит от порядка включения
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
Каждый из факторов по отношению к модели только без него, но со всеми остальными. Нужно, если много факторов и выборки разного размера. Тогда результат не будет зависеть от порядка включения факторов в модель.
# 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")])
ggplot(wt_mod_2_diag, aes(x = 1:nrow(wt_mod_2_diag), y = .cooksd)) + geom_bar(stat = "identity")
gg_resid <- ggplot(data = wt_mod_2_diag, aes(x = .fitted, y = .stdresid)) + geom_point() + geom_hline(yintercept = 0) gg_resid
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)
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
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))
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.
Logan M. 2010. Biostatistical Design and Analysis Using R. A Practical Guide