class: center, middle, inverse, title-slide #
Week 9: Scaling, Contrasts, Interactions
## Univariate Statistics and Methodology using R ### Martin Corley ### Department of Psychology
The University of Edinburgh --- class: inverse, center, middle # Part 1 ## Scaling --- # Learning to Read .pull-left.pulse.animated[ ![](lecture_8_files/img/playmo_teach.jpg) ] .pull-right[ .center[
age
hrs_wk
method
R_AGE
10.115
4.971
phonics
14.272
9.940
4.677
phonics
13.692
6.060
4.619
phonics
10.353
9.269
4.894
phonics
12.744
10.991
5.035
phonics
15.353
6.535
5.272
word
5.798
8.150
6.871
word
8.691
7.941
4.053
word
6.988
8.233
5.474
word
8.713
6.219
4.038
word
5.908
]] --- # Learning to Read ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) -2.423 2.472 -0.98 0.332 ## age 0.938 0.206 4.55 0.000038 *** ## hrs_wk 0.964 0.418 2.31 0.025 * ## ... ``` --- count: false # Learning to Read ``` ## ... ## Estimate Std. Error t value Pr(>|t|) *## (Intercept) -2.423 2.472 -0.98 0.332 ## age 0.938 0.206 4.55 0.000038 *** ## hrs_wk 0.964 0.418 2.31 0.025 * ## ... ``` - as we noted last week, the _intercept_ for this model is nonsensical + "children aged zero who read for zero hours a week have a predicted reading age of -2.423" - perhaps there's something we can do about this? --- # One-Predictor Model .pull-left[ - let's start with a model with a _single_ predictor of age<sup>1</sup> ```r # model mod2 <- lm(R_AGE ~ age,data=reading) # figure p <- reading %>% ggplot(aes(x=age,y=R_AGE)) + xlab("age") + ylab("reading age") + geom_point(size=3) + geom_smooth(method="lm") p ``` ] .pull-right[ ![](lecture_8_files/figure-html/ggp-1.svg) ] .footnote[ <sup>1</sup> we know this model doesn't meet assumptions, but it will work for an illustration ] ??? - animate the x-axis changes? (Unlikely to work, maybe as .svg) --- # Changing the Intercept .pull-left[ - actually it's fairly easy to move the intercept - we can just pick a "useful-looking" value - for example, we might want the intercept to tell us about students at age 8 + this is a decision; no magic about it ] .pull-right[ ![](lecture_8_files/figure-html/ggp2-1.svg)<!-- --> ] --- count: false # Changing the Intercept .pull-left[ - actually it's fairly easy to move the intercept - we can just pick a "useful-looking" value - for example, we might want the intercept to tell us about students at age 8 + this is a decision; no magic about it ] .pull-right[ ![](lecture_8_files/figure-html/ggp3-1.svg)<!-- --> ] --- # A Model With a New Intercept ### original model ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 1.764 1.753 1.01 0.32 ## age 1.012 0.212 4.76 0.000018 *** ## ... ``` ### new model ```r *mod2b <- lm(R_AGE ~ I(age-8), data=reading) summary(mod2b) ``` ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 9.862 0.383 25.77 < 2e-16 *** ## I(age - 8) 1.012 0.212 4.76 0.000018 *** ## ... ``` --- # Fit Remains Unchanged ### original model ``` ## ... ## Multiple R-squared: 0.321, Adjusted R-squared: 0.307 ## F-statistic: 22.7 on 1 and 48 DF, p-value: 0.0000179 ``` ### new model ``` ## ... ## Multiple R-squared: 0.321, Adjusted R-squared: 0.307 ## F-statistic: 22.7 on 1 and 48 DF, p-value: 0.0000179 ``` --- # A Model with a New Slope .pull-left[ - it's also easy to linearly scale the slope - we can just pick a "useful" scale - for example, we might want to examine the effect per month of age + this is a decision; no magic about it ] .pull-right[ ![](lecture_8_files/figure-html/ggp5-1.svg)<!-- --> ] --- count: false # A Model with a New Slope .pull-left[ - it's also easy to linearly scale the slope - we can just pick a "useful" scale - for example, we might want to examine the effect per month of age + this is a decision; no magic about it ] .pull-right[ ![](lecture_8_files/figure-html/ggp4-1.svg)<!-- --> ] --- # A Model With a New Slope ### original model ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 1.764 1.753 1.01 0.32 ## age 1.012 0.212 4.76 0.000018 *** ## ... ``` ### new model ```r *mod2c <- lm(R_AGE ~ I(age*12), data=reading) summary(mod2c) ``` ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 1.7638 1.7534 1.01 0.32 ## I(age * 12) 0.0844 0.0177 4.76 0.000018 *** ## ... ``` --- # Fit Remains Unchanged ### original model ``` ## ... ## Multiple R-squared: 0.321, Adjusted R-squared: 0.307 ## F-statistic: 22.7 on 1 and 48 DF, p-value: 0.0000179 ``` ### new model ``` ## ... ## Multiple R-squared: 0.321, Adjusted R-squared: 0.307 ## F-statistic: 22.7 on 1 and 48 DF, p-value: 0.0000179 ``` --- # We Can Get Fancy About This ```r mod.mb <- lm(R_AGE ~ I((age-8)*12) + I(hrs_wk-mean(hrs_wk)), data=reading) summary(mod.mb) ``` ``` ## ## Call: ## lm(formula = R_AGE ~ I((age - 8) * 12) + I(hrs_wk - mean(hrs_wk)), ## data = reading) ## ## Residuals: ## Min 1Q Median 3Q Max ## -4.385 -2.251 0.326 2.395 3.201 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 9.8659 0.3665 26.92 < 2e-16 *** ## I((age - 8) * 12) 0.0782 0.0172 4.55 0.000038 *** ## I(hrs_wk - mean(hrs_wk)) 0.9636 0.4176 2.31 0.025 * ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 2.59 on 47 degrees of freedom ## Multiple R-squared: 0.39, Adjusted R-squared: 0.364 ## F-statistic: 15 on 2 and 47 DF, p-value: 0.00000896 ``` --- # Which Has a Bigger Effect? .flex.items-center[ .w-40.pa2[ ![](lecture_8_files/img/playmo_age.jpg) ] .w-60.pa2[ - in our two-predictor model, is age more important than practise? Or vice-versa? - hard to tell because the predictors are in different _units_ ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) -2.423 2.472 -0.98 0.332 ## age 0.938 0.206 4.55 0.000038 *** ## hrs_wk 0.964 0.418 2.31 0.025 * ## ... ``` - how do we compare effects of a year of age to those of an hour per week of practise? ]] --- # Standardisation - _if_ the predictors and outcome are very roughly normally distributed... .center[ ![](lecture_8_files/figure-html/hist-1.svg)<!-- --> ] - we can calculate `\(z\)`-scores by subtracting the mean and dividing by the standard deviation `$$z_i=\frac{x_i-\bar{x}}{\sigma_x}$$` --- # Standardisation - in R, the `scale()` function calculates `\(z\)`-scores - in R, you don't need to create new columns! + also don't need to use `I()` because no ambiguity (though you can use it if you want) ```r mod.ms <- lm(scale(R_AGE) ~ scale(age) + scale(hrs_wk), data=reading) ``` -- - the variables are now _all_ in terms of standard deviations from the mean - at the _intercept_, `age` is the mean of age and `hrs_wk` is the mean of hrs_wk - _slopes_: "how many standard deviations does `R_AGE` change for a one standard deviation change in the predictor?" --- # Standardisation ```r summary(mod.ms) ``` ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) -6.86e-17 1.13e-01 0.00 1.000 ## scale(age) 5.25e-01 1.15e-01 4.55 0.000038 *** ## scale(hrs_wk) 2.66e-01 1.15e-01 2.31 0.025 * ## ... ``` - `R_AGE` changes 0.52 sds for a 1-sd change in `age`, and 0.27 sds for a 1-sd change in `hrs_wk` - reasonable conclusion might be that age has a greater effect on reading age than does practice ??? - we _expect_ the intercept to be zero because it's the mean of everything -- - model fit doesn't change with standardisation ``` ## ... ## Multiple R-squared: 0.39, Adjusted R-squared: 0.364 ## F-statistic: 15 on 2 and 47 DF, p-value: 0.00000896 ``` --- # Standardisation Post-Hoc - we can convert "raw" model coefficients `\(b\)` to standardised coefficients `\(\beta\)` without re-running the regression] - for predictor `\(x\)` of outcome `\(y\)`: `$$\beta_x=b_x\cdot{}\frac{\sigma_x}{\sigma_y}$$` - or there's a function to do it for you ```r library(lsr) standardCoefs(mod.m) ``` ``` ## b beta ## age 0.9378 0.5250 ## hrs_wk 0.9636 0.2662 ``` --- class: inverse, center, middle, animated, rotateInDownLeft # End of Part 1 --- class: inverse, center, middle # Part 2 ## Categorical Predictors --- # Playmobil vs. SuperZings .pull-left[ ![](lecture_8_files/img/playmo_2.jpg) ] .pull-right[ - some important pretesting went into these lectures - every individual figure rated for "usefulness" in explaining stats - how do we decide which to use? ] --- count: false #Playmobil vs. SuperZings .pull-left[
type
UTILITY
playmo
3.8
zing
3.8
playmo
7.5
zing
3.7
playmo
6.1
zing
0.3
playmo
5.4
zing
3.7
playmo
3.6
zing
2.6
] .pull-right[ - some important pretesting went into these lectures - every individual figure rated for "usefulness" in explaining stats - how do we decide which to use? ] --- # Playmobil vs. SuperZings .pull-left[
type
UTILITY
playmo
3.8
zing
3.8
playmo
7.5
zing
3.7
playmo
6.1
zing
0.3
playmo
5.4
zing
3.7
playmo
3.6
zing
2.6
] .pull-right[ - we already know one way to answer this ```r t.test(UTILITY~type, data=toys, * var.equal=TRUE) ``` ``` ## ## Two Sample t-test ## ## data: UTILITY by type *## t = 2.5, df = 8, p-value = 0.04 ## alternative hypothesis: true difference in means is not equal to 0 ## 95 percent confidence interval: ## 0.1809 4.7391 ## sample estimates: ## mean in group playmo mean in group zing ## 5.28 2.82 ``` ] --- # The Only Equation You'll Ever Need - which toys are the most useful? .br3.pa2.bg-gray[ `$$\color{red}{\textrm{outcome}_i}\color{white}=\color{blue}{(\textrm{model})_i}\color{white}{+\textrm{error}_i}$$` `$$\color{red}{\textrm{utility}_i}\color{white}{=}\color{blue}{(\textrm{some function of type})_i}\color{white}{+\epsilon_i}$$` ] - we need to represent `type` as a number - the simplest way of doing this is to use 0 or 1 --- # Quantifying a Nominal Predictor .pull-left[ ```r toys <- toys %>% mutate(is_playmo = ifelse(type=="playmo",1,0)) toys ``` ``` ## # A tibble: 10 x 3 ## type UTILITY is_playmo ## <fct> <dbl> <dbl> ## 1 playmo 3.8 1 ## 2 zing 3.8 0 ## 3 playmo 7.5 1 ## 4 zing 3.7 0 ## 5 playmo 6.1 1 ## 6 zing 0.3 0 ## 7 playmo 5.4 1 ## 8 zing 3.7 0 ## 9 playmo 3.6 1 ## 10 zing 2.6 0 ``` ] -- .pull-right[ - this maps to a linear model `$$\color{red}{\textrm{utility}_i}=\color{blue}{b_0+b_1\cdot{}\textrm{is_playmo}}+\epsilon_i$$` - `\(\overline{\textrm{utility}}\)` for SuperZings is **intercept** - "change due to playmo-ness" is **slope** ] --- # Linear Model Using `is_playmo` ```r mod1 <- lm(UTILITY~is_playmo,data=toys) summary(mod1) ``` ``` ## ## Call: ## lm(formula = UTILITY ~ is_playmo, data = toys) ## ## Residuals: ## Min 1Q Median 3Q Max ## -2.52 -1.17 0.47 0.88 2.22 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 2.820 0.699 4.04 0.0038 ** *## is_playmo 2.460 0.988 2.49 0.0376 * ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 1.56 on 8 degrees of freedom ## Multiple R-squared: 0.436, Adjusted R-squared: 0.366 ## F-statistic: 6.2 on 1 and 8 DF, p-value: 0.0376 ``` ??? - note that the `\(t\)` value (and the `\(p\)` value) are exactly what we got from our initial `\(t\)`-test - the `\(t\)`-test is just a special case of the linear model --- # Let R Do the Work ```r contrasts(toys$type) ``` ``` ## zing ## playmo 0 ## zing 1 ``` - already built-in to factors - NB the first value will be the default intercept (because `\(b_n=0\)` for that value) + can change this using the `relevel()` function (or tidyverse `fct_relevel()`) - as long as we have a _factor_, can just use lm() with that column --- # Linear Model Using `type` ```r mod2 <- lm(UTILITY~type, data=toys) summary(mod2) ``` ``` ## ## Call: ## lm(formula = UTILITY ~ type, data = toys) ## ## Residuals: ## Min 1Q Median 3Q Max ## -2.52 -1.17 0.47 0.88 2.22 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 5.280 0.699 7.56 0.000066 *** *## typezing -2.460 0.988 -2.49 0.038 * ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 1.56 on 8 degrees of freedom ## Multiple R-squared: 0.436, Adjusted R-squared: 0.366 ## F-statistic: 6.2 on 1 and 8 DF, p-value: 0.0376 ``` ??? - point out why sign is reversed! - point out `typezing` label --- # Graphically .center[ ![](lecture_8_files/figure-html/ggpA-1.svg)<!-- --> ] - shows "what the model is doing", but isn't a very good presentation - the line suggests you can make predictions for types between _playmo_ and _zing_ --- # Graphically .center[ ![](lecture_8_files/figure-html/ggpB-1.svg)<!-- --> ] - error bars represent one standard error of the mean --- # What About Lego Figures? .pull-left[ ![](lecture_8_files/img/playmo_3.jpg) ] .pull-right[ - we now have three groups - can't label them `c(0, 1, 2)` because that would express a linear relationship ![](lecture_8_files/figure-html/minig-1.svg)<!-- --> ] --- # Independent Effects - "change due to lego-ness" is _independent_ of change due to anything else - solution: add another predictor ```r toys <- toys %>% mutate( is_playmo = ifelse(type=="playmo",1,0), is_lego = ifelse(type=="lego",1,0) ) head(toys) ``` ``` ## # A tibble: 6 x 4 ## type UTILITY is_playmo is_lego ## <fct> <dbl> <dbl> <dbl> ## 1 zing 3.8 0 0 ## 2 playmo 3.8 1 0 ## 3 lego 1.8 0 1 ## 4 zing 3.7 0 0 ## 5 playmo 7.5 1 0 ## 6 lego 3.6 0 1 ``` --- # Three-Level Predictor: Two Coefficients .flex.items-center[ .w-40.pa2[
type
UTILITY
is_playmo
is_lego
zing
3.8
0
0
playmo
3.8
1
0
lego
1.8
0
1
zing
3.7
0
0
playmo
7.5
1
0
lego
3.6
0
1
] .w-60.pa2[ `$$\textrm{UTILITY}_i=\color{blue}{b_0}\color{gray}{+b_1\cdot\textrm{is_playmo}_i+b_2\cdot\textrm{is_lego}_i}+\epsilon_i$$` `$$\textrm{UTILITY}_i=\color{blue}{b_0}\color{gray}{+b_1\cdot0+b_2\cdot0}+\epsilon_i$$` .tc.pt3[ "utility of a zing" ] ]] --- count: false # Three-Level Predictor: Two Coefficients .flex.items-center[ .w-40.pa2[
type
UTILITY
is_playmo
is_lego
zing
3.8
0
0
playmo
3.8
1
0
lego
1.8
0
1
zing
3.7
0
0
playmo
7.5
1
0
lego
3.6
0
1
] .w-60.pa2[ `$$\textrm{UTILITY}_i=\color{blue}{b_0}\color{red}{+b_1\cdot\textrm{is_playmo}_i}+\color{gray}{b_2\cdot\textrm{is_lego}_i}+\epsilon_i$$` `$$\textrm{UTILITY}_i=\color{blue}{b_0}\color{red}{+b_1\cdot1}+\color{gray}{b_2\cdot0}+\epsilon_i$$` .tc.pt3[ "change in utility from a zing due to being a playmo" ] ]] --- count: false # Three-Level Predictor: Two Coefficients .flex.items-center[ .w-40.pa2[
type
UTILITY
is_playmo
is_lego
zing
3.8
0
0
playmo
3.8
1
0
lego
1.8
0
1
zing
3.7
0
0
playmo
7.5
1
0
lego
3.6
0
1
] .w-60.pa2[ `$$\textrm{UTILITY}_i=\color{blue}{b_0}\color{gray}{+b_1\cdot\textrm{is_playmo}_i}+\color{red}{b_2\cdot\textrm{is_lego}_i}+\epsilon_i$$` `$$\textrm{UTILITY}_i=\color{blue}{b_0}\color{gray}{+b_1\cdot0}+\color{red}{b_2\cdot1}+\epsilon_i$$` .tc.pt3[ "change in utility from a zing due to being a lego" ] ]] --- # R Has Our Backs .pull-left[ - this is the _default_ contrast coding in R - known as **treatment** (or **dummy**) contrasts ```r contrasts(toys$type) ``` ``` ## playmo lego ## zing 0 0 ## playmo 1 0 ## lego 0 1 ``` ] -- .pull-right[ ### a subtle difference .fr[![:scale 80%](lecture_8_files/img/danger.svg)] ```r # core R: alphabetical contrasts(as.factor(toys$type)) ``` ``` ## playmo zing ## lego 0 0 ## playmo 1 0 ## zing 0 1 ``` ```r # tidyverse: order of mention contrasts(as_factor(toys$type)) ``` ``` ## playmo lego ## zing 0 0 ## playmo 1 0 ## lego 0 1 ``` ] --- # A Linear Model ```r mod <- lm(UTILITY ~ type, data=toys) summary(mod) ``` ``` ## ## Call: ## lm(formula = UTILITY ~ type, data = toys) ## ## Residuals: ## Min 1Q Median 3Q Max ## -2.52 -0.70 0.12 0.88 2.22 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 2.820 0.612 4.61 0.00061 *** ## typeplaymo 2.460 0.866 2.84 0.01487 * ## typelego -0.020 0.866 -0.02 0.98195 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 1.37 on 12 degrees of freedom ## Multiple R-squared: 0.475, Adjusted R-squared: 0.387 ## F-statistic: 5.42 on 2 and 12 DF, p-value: 0.021 ``` ??? - this is like a form of multiple regression + 3 levels -> 2 predictors - so we can say that playmo are better than zing (we can see that zing is the intercept because it's omitted from the table) - we can say that lego are not better than zing - _playmo and lego are not directly compared_ - to do this, we would need a different contrast coding scheme --- ![:scale 5%](lecture_8_files/img/danger.svg) .f1[Graphically] .pull-left[ ```r gd <- toys %>% group_by(type) %>% summarise(mean_se(UTILITY)) gd ``` ``` ## # A tibble: 3 x 4 ## type y ymin ymax ## <fct> <dbl> <dbl> <dbl> ## 1 zing 2.82 2.15 3.49 ## 2 playmo 5.28 4.55 6.01 ## 3 lego 2.8 2.42 3.18 ``` ```r gd %>% ggplot(aes(x=type,y=y, ymin=ymin,ymax=ymax)) + geom_bar(stat="identity") + geom_errorbar(width=.2) + ylab("UTILITY") ``` ] .pull-right[ ![](lecture_8_files/figure-html/ggpB2-1.svg) ] --- # Contrast Coding - there may be a different contrast coding which better suits our research interests - for a predictor with `\(g\)` levels (or "groups") there are `\(g-1\)` possible contrasts - these can be anything you like (values don't have to be zero or one): there are a few built in to R - usefulness depends on your research question - contrasts act like "tests of differences of interest" once your model has been fit - model fit is not affected by the choice of contrasts<sup>1</sup> .footnote[ <sup>1</sup> for type 1 sums of squares ] --- class: inverse, center, middle, animated, rotateInDownLeft # End of Part 2 --- class: inverse, center, middle # Part 3 ## Interactions --- # Back to Reading .pull-left[ ![](lecture_8_files/img/playmo_teach.jpg) ] .pull-right[ .center[
age
hrs_wk
method
R_AGE
10.115
4.971
phonics
14.272
9.940
4.677
phonics
13.692
6.060
4.619
phonics
10.353
9.269
4.894
phonics
12.744
10.991
5.035
phonics
15.353
6.535
5.272
word
5.798
8.150
6.871
word
8.691
7.941
4.053
word
6.988
8.233
5.474
word
8.713
6.219
4.038
word
5.908
]] --- # We Know Enough to Fit a Linear Model ```r mod3 <- lm(R_AGE~method,data=reading) summary(mod3) ``` ``` ## ## Call: ## lm(formula = R_AGE ~ method, data = reading) ## ## Residuals: ## Min 1Q Median 3Q Max ## -3.96 -1.44 0.36 1.39 3.49 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 12.485 0.395 31.59 < 2e-16 *** ## methodword -5.135 0.559 -9.19 3.8e-12 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 1.98 on 48 degrees of freedom ## Multiple R-squared: 0.637, Adjusted R-squared: 0.63 ## F-statistic: 84.4 on 1 and 48 DF, p-value: 3.76e-12 ``` --- # We Know Enough to Draw a Graph .center[ ![](lecture_8_files/figure-html/rg-1.svg)<!-- --> ] - we also know enough to run model diagnostics --- .center[ ![](lecture_8_files/figure-html/diag-1.svg)<!-- --> ] --- # Adding Predictors - we also know that `hrs_wk` affects reading age - we can build a multiple regression, and inspect the coefficients ```r mod.m2 <- lm(R_AGE ~ hrs_wk + method,data=reading) summary(mod.m2) ``` ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 7.843 1.524 5.15 5.1e-06 *** ## hrs_wk 0.914 0.291 3.14 0.0029 ** ## methodword -4.932 0.518 -9.53 1.5e-12 *** ## ... ``` ??? - we're sticking to the one predictor for simplicity here --- # Graphically .center[ ![](lecture_8_files/figure-html/fancyg-1.svg)<!-- --> ] - note that according to this model the lines are parallel - an hour of practice has _exactly the same_ effect, however you're taught --- # Different Effects for Different Methods ```r mod.m3 <- lm(R_AGE ~ hrs_wk + method + hrs_wk:method,data=reading) summary(mod.m3) ``` ``` ## ## Call: ## lm(formula = R_AGE ~ hrs_wk + method + hrs_wk:method, data = reading) ## ## Residuals: ## Min 1Q Median 3Q Max ## -3.449 -1.377 -0.092 1.428 2.936 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 4.528 1.916 2.36 0.02238 * ## hrs_wk 1.567 0.371 4.22 0.00011 *** ## methodword 2.228 2.780 0.80 0.42697 ## hrs_wk:methodword -1.445 0.552 -2.62 0.01199 * ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 1.71 on 46 degrees of freedom ## Multiple R-squared: 0.739, Adjusted R-squared: 0.722 ## F-statistic: 43.4 on 3 and 46 DF, p-value: 1.81e-13 ``` --- # Different Effects for Different Methods .center[ ![](lecture_8_files/figure-html/fif-1.svg)<!-- --> ] --- # Interaction is Just Multiplication .br3.pa2.bg-gray.white[ `$$\hat{y}_i=b_0+b_1x_{1i}+b_2x_{2i}+\color{red}{b_3x_{1i}x_{2i}}$$` ] `$$\widehat{\textrm{R_AGE}}=b_0+b_1\cdot\textrm{hrs_wk}+b_2\cdot\textrm{word}+b_3\cdot\textrm{hrs_wk}\cdot\textrm{word}$$` - when `\(\textrm{word}=0\)`: `$$\widehat{\textrm{R_AGE}}=b_0+b_1\cdot\textrm{hrs_wk}+\color{gray}{b_2\cdot0+b_3\cdot\textrm{hrs_wk}\cdot0}$$` - when `\(\textrm{word}=1\)`: `$$\widehat{\textrm{R_AGE}}=b_0+b_1\cdot\textrm{hrs_wk}+b_2\cdot1+b_3\cdot\textrm{hrs_wk}\cdot1$$` --- count: false # Interaction is Just Multiplication .br3.pa2.bg-gray.white[ `$$\hat{y}_i=b_0+b_1x_{1i}+b_2x_{2i}+\color{red}{b_3x_{1i}x_{2i}}$$` ] `$$\widehat{\textrm{R_AGE}}=\color{blue}{4.53}+\color{blue}{1.57}\cdot\textrm{hrs_wk}+\color{blue}{2.23}\cdot\textrm{word}+\color{blue}{-1.44}\cdot\textrm{hrs_wk}\cdot\textrm{word}$$` - when `\(\textrm{word}=0\)`: `$$\widehat{\textrm{R_AGE}}=\color{blue}{4.53}+\color{blue}{1.57}\cdot\textrm{hrs_wk}+\color{gray}{2.23\cdot0+-1.44\cdot\textrm{hrs_wk}\cdot0}$$` - when `\(\textrm{word}=1\)`: `$$\widehat{\textrm{R_AGE}}=\color{blue}{4.53}+\color{blue}{1.57}\cdot\textrm{hrs_wk}+\color{blue}{2.23}\cdot1+\color{blue}{-1.44}\cdot\textrm{hrs_wk}\cdot1$$` --- # A Nice Graph .pull-left[ ```r reading %>% ggplot( aes(x=hrs_wk,y=R_AGE,colour=method)) + xlab("practice") + ylab("reading age") + geom_point(size=3) + geom_smooth(method="lm") ``` ] .pull-right[ ![](lecture_8_files/figure-html/ng-1.svg) ] --- # Interaction Really _Is_ Just Multiplication - in our dataset it's also possible that age and practice interact .br3.pa2.bg-gray.white.tc[ "effect of practice is not constant across ages" `$$\hat{y}_i=b_0+b_1x_{1i}+b_2x_{2i}+\color{red}{b_3x_{1i}x_{2i}}$$` ] ```r mod.m4 <- lm(R_AGE ~ age + hrs_wk + age:hrs_wk, data=reading) ``` -- .tc.pt2[ `a + b + a:b` can also be written `a * b` ] ```r mod.m4 <- lm(R_AGE ~ age * hrs_wk, data=reading) ``` --- # Interaction of Age and Practice ```r summary(mod.m4) ``` ``` ## ## Call: ## lm(formula = R_AGE ~ age * hrs_wk, data = reading) ## ## Residuals: ## Min 1Q Median 3Q Max ## -5.445 -1.967 -0.336 2.302 3.925 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 16.596 9.714 1.71 0.094 . ## age -1.449 1.198 -1.21 0.233 ## hrs_wk -3.079 2.041 -1.51 0.138 *## age:hrs_wk 0.504 0.249 2.02 0.049 * ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 2.51 on 46 degrees of freedom ## Multiple R-squared: 0.44, Adjusted R-squared: 0.403 ## F-statistic: 12 on 3 and 46 DF, p-value: 0.00000607 ``` ??? - note that the effects of age and of practice are not reliably different from zero --- # Interaction Effect ``` ## ... ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 16.596 9.714 1.71 0.094 . ## age -1.449 1.198 -1.21 0.233 ## hrs_wk -3.079 2.041 -1.51 0.138 ## age:hrs_wk 0.504 0.249 2.02 0.049 * ## ... ``` .br3.pa2.bg-gray.white.tc[ `$$\widehat{\textrm{R_AGE}}_i=b_0+b_1\cdot\textrm{age}_i+b_2\cdot\textrm{hrs_wk}_i+b_3\cdot\textrm{age}_i\cdot\textrm{hrs_wk}_i$$` ] .pull-left[ #### age 7; hrs_wk 5 `$$16.6+-1.45\cdot7+-3.08\cdot5+0.5\cdot7\cdot5$$` `$$\color{red}{=8.55}$$` ] .pull-right[ #### age 12; hrs_wk 6 `$$16.6+-1.45\cdot12+-3.08\cdot6+0.5\cdot12\cdot6$$` `$$\color{red}{=16.72}$$` ] --- # Significance ``` ## ... ## Estimate Std. Error t value Pr(>|t|) *## (Intercept) 16.596 9.714 1.71 0.094 . *## age -1.449 1.198 -1.21 0.233 *## hrs_wk -3.079 2.041 -1.51 0.138 ## age:hrs_wk 0.504 0.249 2.02 0.049 * ## ... ``` - note that not all of the effects are significant - the model's best guess at the data ( `\(\widehat{\textrm{R_AGE}}\)` ) is expressed by the coefficients - but we're not confident that the highlighted effects would reliably differ from zero less than 5% of the time if we repeatedly sampled from the same population - so the _predictions_ of the model are as above (and below) but our _conclusion_ is only that practise is more beneficial the older a child is --- # Graphical Model .center[
] --- class: inverse, center, middle, animated, rotateInDownLeft # End --- # Acknowledgements - icons by Diego Lavecchia from the [Noun Project](https://thenounproject.com/)