-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.Rmd
More file actions
1865 lines (1342 loc) · 54.1 KB
/
Copy pathindex.Rmd
File metadata and controls
1865 lines (1342 loc) · 54.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
title: "Patterns for Regression Models"
author: "J Faleiro"
date: "April 10, 2015"
output:
html_document:
keep_md: true
toc: true
theme: united
---
# Required libraries
```{r, warning=FALSE, message=FALSE}
if (!require("pacman")) install.packages("pacman")
pacman::p_load(datasets, UsingR, reshape, ggplot2, manipulate, dplyr, GGally, stats, rgl, car)
```
# Why Statisticians Love Confusing Synonyms?
Various names for the same thing: variable independence
Independent Variable | Dependent Variable
---------------------|--------------------
X axis | Y axis
Predictor | Outcome
Predictor | Predicted
Regressor | Outcome
The function `lm` needs a formula of the form dependent ~ independent (or predicted ~ predictor).
# Basic Least Squares
### Finding Least Squares
Finding the least (i.e. that minimizes) squares (to ensure points below and above the line are treated the same) is to find the minimum value of the following equation:
$\sum_{i=1}^{n} (Y_i - \mu)^2$
```{r}
y <- c(0.8, 0.47, 0.51, 0.73, 0.36, 0.58, 0.57, 0.85, 0.44, 0.42)
leastSquares <- function(mu) { sum((y - mu)^2) }
optimize(leastSquares, interval=c(-100, 100), maximum=FALSE)
```
What in theory should match $\bar{Y}$:
```{r}
mean(y)
```
What if we get something a bit more elaborate:
$\sum_{i=1}^{n} w_i(x_i - \mu)^2$
What would be the value of $\mu$ that would minimize the least square equation?
```{r}
x <- c(0.18, -1.54, 0.42, 0.95)
w <- c(2, 1, 3, 1)
leastSquares <- function(mu) { sum(w*(x - mu)^2) }
optimize(leastSquares, interval=c(-100, 100), maximum=FALSE)
```
### Heights of Parents and Children
```{r}
library(UsingR); data(galton); library(reshape)
describe(galton)
head(galton)
```
Make it wide:
```{r , message=FALSE}
long <- melt(galton)
describe(long)
head(long)
```
Plot distributions of children and parents, heights in inches.
```{r}
ggplot(long, aes(x=value, fill=variable)) +
geom_histogram(colour='black', binwidth=1) +
facet_grid(. ~ variable)
```
Comparing children and (average over the pair of) parents heights:
```{r}
ggplot(galton, aes(x=parent, y=child)) +
geom_point()
```
A bad plot, no indication of when a point is plotted over it a number of times. We can do a bit better by using `plot` and `jitter`:
```{r}
plot(jitter(child, 4) ~ parent, galton)
```
The regression line of children ~ parent can be calculated by `lm`. The function `lm` needs a formula of the form dependent ~ independent (or predicted ~ predictor).
```{r}
regrline <- lm(child ~ parent, galton)
summary(regrline)
```
The first thing we can notice is that the mean of the residuals of regrline is close to zero:
```{r}
mean(regrline$residuals)
```
And also the correlation between residuals and predictors will be close to zero, i.e. they are uncorrelated.
```{r}
cov(regrline$residuals, galton$parent)
```
The intercept $\beta_0$ is the first element of regrline$coef:
```{r}
regrline$coef[1]
```
The slope $\beta_1$ is the second element of regrline$coef:
```{r}
regrline$coef[2]
```
A coefficient will be within 2 standard errors of its estimate about 95% of the time. This means the slope of our
regression is significantly different than either 0 or 1 since (.64629) +/- (2*.04114) is near neither 0 nor 1.
We can see that the coeficient (multiplier) of parents to children is given by $0.64629 \pm 2 * 0.04114$
And we can add the regression line to the original plot:
```{r}
plot(jitter(child, 4) ~ parent, galton)
abline(regrline, lwd=3, col='red')
```
We can get a plot with the same information using `ggplot2`:
```{r}
freqData <- as.data.frame(table(galton$child, galton$parent))
names(freqData) <- c("child", "parent", "freq")
freqData$child <- as.numeric(as.character(freqData$child))
freqData$parent <- as.numeric(as.character(freqData$parent))
head(freqData)
```
```{r}
ggplot(filter(freqData, freq > 0), aes(x = parent, y = child)) +
scale_size(range = c(2, 20), guide = "none" ) +
geom_point(colour="grey50", aes(size = freq+20, show_guide = FALSE)) +
geom_point(aes(colour=freq, size = freq)) +
scale_colour_gradient(low = "lightblue", high="white")
```
We can calculate the optimal linear regression:
```{r}
lm(I(child - mean(child)) ~ I(parent - mean(parent)) -1, data=galton)
```
Shows the value of $\beta$ through which you minimize the mean square error given by $\sum_{i=1}^{n} {(Y_i - \beta X_i)}^2$, what is 0.646
That's how it looks like graphically:
```{r}
lm1 <- lm(galton$child ~ galton$parent)
ggplot(filter(freqData, freq > 0), aes(x = parent, y = child)) +
scale_size(range = c(2, 20), guide = "none" ) +
geom_point(colour="grey50", aes(size = freq+20, show_guide = FALSE)) +
geom_point(aes(colour=freq, size = freq)) +
scale_colour_gradient(low = "lightblue", high="white") +
geom_abline(intercept = coef(lm1)[1], slope = coef(lm1)[2], size = 1, colour = grey(.5))
```
### Linear Least Squares
```{r}
y <- galton$child
x <- galton$parent
beta1 <- cor(y, x) * sd(y)/sd(x)
beta0 <- mean(y) - beta1 * mean(x)
c(beta0, beta1)
```
In R, `lm()` does a linear regression and is used in different ways. Here we will regress `y` as the predictor and `x` as the outcome. The function `coef()` gets the output of the linear model and just grabs the coeficient:
```{r}
coef(lm(y ~ x))
```
The coeficients are exactly beta0 and beta1 we calculated above.
If we reverse the outcome/predictor relationships, we switch the model:
```{r}
beta1 <- cor(y, x) * sd(x)/sd(y)
beta0 <- mean(x) - beta1 * mean(y)
rbind(c(beta0, beta1), coef(lm(x ~ y)))
```
Same values.
Now, checking $\beta_1$ and $\beta_0$ when a regression is through the origin $(x=0, y=0)$.
If through the origin, $\beta_0 = 0$. Now $\beta_1$:
```{r}
yc <- y - mean(y)
xc <- x - mean(x)
beta1 <- sum(yc * xc) / sum(xc ^ 2)
c(beta1, coef(lm(y ~ x))[2])
```
They both yield the same result. You get the same slope if you use yc and xc, as long as you subtract the intercept (-1):
```{r}
lm(formula = yc ~ xc -1)
```
You can also use normalized $X_i$ and $Y_i$ and the slope of $lm(Zy_i, Zx_i)$ will be the same as $cor(Y_i,X_i)$ and the same as $cor(Zy_i, Zx_i)$:
```{r}
yn <- (y - mean(y))/sd(y) # normalized Y
xn <- (x - mean(x))/sd(x) # normalized X
c(cor(y, x), cor(yn, xn), coef(lm(yn ~ xn))[2])
```
The best way to add a linear regression line to a plot is by adding a layer `geom_smooth` to a plot, using `lm` as a method and `y ~ x` as the formula (what is the default):
```{r}
ggplot(filter(freqData, freq > 0), aes(x = parent, y = child)) +
scale_size(range = c(2, 20), guide = "none" ) +
geom_point(colour="grey50", aes(size = freq+20, show_guide = FALSE)) +
geom_point(aes(colour=freq, size = freq)) +
scale_colour_gradient(low = "lightblue", high="white") +
geom_smooth(method='lm', formula=y~x)
```
You can see that a confidence interval (shaded area) is given for free with a `geom_smooth` layer. The statistical uncertainty is added automatically.
### Regression to the mean
Y is related to son's height and X to the father's height, both normalized:
```{r}
y <- (father.son$sheight - mean(father.son$sheight)) / sd(father.son$sheight)
x <- (father.son$fheight - mean(father.son$fheight)) / sd(father.son$fheight)
rho <- cor(x, y)
```
Since x and y are normalized:
```{r}
c(sd(x), sd(x))
c(mean(x), mean(y))
```
The mean is almost zero.
We will plot with a few assumptions:
* we set x and y limits as (-4,4) - since this is in SDs, the chance of something falling beyond that (4 SDs away from the mean) is dim
* the line `geom_abline(intercept=0, slope=1)` is the identity line, what would be the regression line if no noise, i.e. X and Y perfectly correlated.
* the line `geom_abline(intercept=0, slope=rho, size=2)`, in red, is the line showing son's height as the outcome and parent's height as the predictor
* the line `geom_abline(intercept=0, slope=1/rho, size=2)` is the line showing son's height as the predictor and parent's height as the outcome
```{r}
ggplot(data.frame(x-x, y=y), aes(x = x, y = y)) +
geom_point(colour="black", alpha=0.2, size=3) +
geom_point(colour="salmon", alpha=0.2, size=2) +
xlim(-4,4) + ylim(-4,4) +
geom_vline(xintercept = 0) +
geom_hline(yintercept = 0) +
geom_abline(intercept=0, slope=1) +
geom_abline(intercept=0, slope=rho, size=1.5, colour='red') +
geom_abline(intercept=0, slope=1/rho, size=1.5)
```
The fitted lines are shown with double tickness (size=2).
Examples of use:
* if we get a parent height as the outcome that is +2 SDs from the mean (on X axis) we can predict that son's height (predictor) should be ~ +1 SD from the mean (regression on the red line, slope = $\rho$)
* if we get a son height as the outcome that is +2 SDs from the mean (on X axis) we can predict that parent's height (predictor) should be ~ +1 SD from the mean (regression on the black line, slope = $1 / \rho$)
# Statistical Linear Regression Model
Linear regression of diamonds in singaporean dollars:
```{r}
data(diamond)
ggplot(diamond, aes(x=carat, y=price)) +
xlab('mass (carats)') +
ylab('price (SIN$)') +
geom_point(size=6, colour='black', alpha=0.2) +
geom_point(size=5, colour='blue', alpha=0.2) +
geom_smooth(method='lm', colour='black')
```
```{r}
fit <- lm(price ~ carat, diamond)
coef(fit)
```
What is says is:
* we estimate a SIN$ 3,721.02 increase in price for every carat in a diamond
* a zero carat diamond should cost SIN$ -259.63 (what doesn't make any sense)
Let's deal with a non-sense intercept (second bullet) my subtracting the mean sized diamond from carat size:
```{r}
fit2 <- lm(price ~ I(carat - mean(carat)), data=diamond) # adjustments have to be surrounded by I() function
coef(fit2)
```
The slope hasn't changed, but the intercept makes more sense: SIN$ 500.08 is the expected price to be paid for an average size diamond.
We can make the model better, the slope is a factor of a large amount of money - we can scale volume by 10:
```{r}
fit3 <- lm(price ~ I(carat*10 - mean(carat*10)), data=diamond) # adjustments have to be surrounded by I() function
coef(fit3)
```
So, each tenth of carat increase will represent a difference in price of SIN$ 372.10
How to predict prices?
Given 3 diamonds and their sizes:
```{r}
newx <- c(0.16, 0.27,0.34)
```
First way, simple calculation $Y_i = \beta_0 + \beta_1 X_i$:
```{r}
coef(fit)[1] + coef(fit)[2] * newx
```
Second way, using `predict`
```{r}
predict(fit, newdata=data.frame(carat=newx))
```
Both yield the same results.
# Effect of scale conversion in coefficients
What happens if I divide a scale of X by 10?
```{r}
x <- c(0.61, 0.93, 0.83, 0.35, 0.54, 0.16, 0.91, 0.62, 0.62)
y <- c(0.67, 0.84, 0.6, 0.18, 0.85, 0.47, 1.1, 0.65, 0.36)
summary(lm(y ~ x))$coefficients
```
```{r}
summary(lm(y ~ I(x/10)))$coefficients
```
Gets multiplied by 10.
What happens if I add a constant K to the regressor?
```{r}
summary(lm(y ~ I(x + 3)))$coefficients
```
The intercept changed, the relationship:
```{r}
0.1884572 - 3*0.722421
```
The new intercept would be $\hat \beta_0 = \beta_0 - K\beta_1$
Another example using `mtcars`. How should a regressor associated to half of weight be interpreted?
```{r}
data(mtcars)
summary(lm(mpg ~ wt + factor(cyl), data=mtcars))$coef
```
```{r}
summary(lm(mpg ~ I(wt * 0.5) + factor(cyl), data = mtcars))$coef
```
The estimate `I(wt * 0.5) = -6.411227` gives the estimated change in mpg per half ton increase in weight.
# Residuals
## Residuals Properties
Calculating residuals of price and carat correlation data and checking some of the residuals properties:
```{r}
data(diamond)
y <- diamond$price
x <- diamond$carat
fit <- lm(y ~ x)
e <- resid(fit)
yhat <- predict(fit)
```
Checking residuals, $e_i = Y_i - \hat Y_i$ so $e_i - (Y_i - \hat Y_i) = 0$
```{r}
max(abs(e - (y - yhat)))
```
Almost zero, what should be the same as
```{r}
max(abs(e - (y - coef(fit)[1] - coef(fit)[2] * x)))
```
Expected value of residuals is zero, $E[e_i] = 0$
```{r}
mean(e)
```
Sum of residuals is zero, $\sum{i=1}_n e_i = 0$ if intercept is included:
```{r}
sum(e)
```
Sum of regressor times residuals is zero, $\sum{i=1}_n e_i x_i = 0$ if regressor is included:
```{r}
sum(e * x)
```
## Visual Patterns of Residual Plots
Plotting prices, mass, regression and a red line for residuals:
```{r}
n <- length(y)
plot(x, y, xlab='mass (carats)', ylab='price (SIN$)',
bg='lightblue',
col='black', cex=1.1, pch=21, frame=FALSE)
abline(fit, lwd=2)
for (i in 1:n)
lines(c(x[i], x[i]), c(y[i], yhat[i]), col='red', lwd=2)
```
This is not the best way to represent residuals (check the amount of unused space above and below the regression line). Instead, let's plot regressors versus residuals:
```{r}
plot(x, e, xlab='mass (carats)', ylab='residuals (SIN$)',
bg='lightblue',
col='black', cex=1.1, pch=21, frame=FALSE)
abline(h=0, lwd=2)
for (i in 1:n)
lines(c(x[i], x[i]), c(e[i], 0), col='red', lwd=2)
```
A few things a residual versus regressor plot should show:
* you should see no patterns of disposition, residuals should spread nicely and without any shape above and below the intercept
* since the intercept is included, red lines should add to ~ zero (positive above the intercept, negative below the intercept)
Now a few example of patological patterns a residual plot should help highlight
```{r}
x <- runif(100, -3, 3)
y <- x + sin(x) + rnorm(100, sd=.2)
```
Basically a uniform distribution on x, and y a senoid oscilation with a bit of random normal noise over it, a regression line defined by `geom_smooth`:
```{r}
ggplot(data.frame(x=x, y=y), aes(x=x,y=y)) +
geom_smooth(method='lm', colour='black') +
geom_point(size=3, colour='black', alpha=0.4) +
geom_point(size=1, colour='red', alpha=0.4)
```
It is not apparent that some pattern is hidden in the data. Let's take a look at the residual plot:
```{r}
e <- resid(lm(y ~ x))
ggplot(data.frame(x=x, y=e), aes(x=x,y=y)) +
xlab("x") + ylab("residual") +
geom_hline(yintercept=0, size=2) +
geom_point(size=3, colour='black', alpha=0.4) +
geom_point(size=1, colour='red', alpha=0.4)
```
Now it is apparent that residuals oscilate over and below the reference line of zero.
Another example:
```{r}
x <- runif(100, 0, 6)
y <- x + rnorm(100, mean=0, sd=.001 * x)
```
X and Y are generated on some pre-determined pattern. X is 100 uniform numbers, Y is X plus 100 random normal numbers - and here is the catch, SD is variable in relation to X - there's the hidden pattern.
A X over Y plot however shows nothing:
```{r}
ggplot(data.frame(x=x, y=y), aes(x=x,y=y)) +
geom_smooth(method='lm', colour='black') +
geom_point(size=3, colour='black', alpha=0.4) +
geom_point(size=1, colour='red', alpha=0.4)
```
Shows nothing. Appears as if X and Y fall exactly on top of the identity line. Let's take a look at the residual plot:
```{r}
e <- resid(lm(y ~ x))
ggplot(data.frame(x=x, y=e), aes(x=x,y=y)) +
xlab("x") + ylab("residual") +
geom_hline(yintercept=0, size=2) +
geom_point(size=3, colour='black', alpha=0.4) +
geom_point(size=1, colour='red', alpha=0.4)
```
Shows that residuals spread as the regressor grows to higher values. There is a name for that, heteroscedasticity.
Heteroscedasticity is a hard word to pronounce, but it doesn't need to be a difficult concept to understand. Put simply, heteroscedasticity (also spelled heteroskedasticity) refers to the circumstance in which the variability of a variable is unequal across the range of values of a second variable that predicts it.
Residual plots are a good tool to diagnose heteroscedasticity.
## Explaining Residuals
Back to our diamond analysis:
```{r}
diamond$e <- resid(lm(price ~ carat, data=diamond))
head(diamond)
```
```{r}
ggplot(diamond, aes(x=carat,y=e)) +
xlab('mass (carats)') +
ylab('residual price (SIN$)') +
geom_hline(yintercept=0, size=2) +
geom_point(size=3, colour='black', alpha=0.4) +
geom_point(size=1, colour='red', alpha=0.4)
```
No patterns, but variance - where is this variance related to:
```{r}
e <- c(resid(lm(price ~ 1, data=diamond)),
resid(lm(price ~ carat, data=diamond)))
fit <- factor(c(rep('intercept', nrow(diamond)),
rep('intercept, slope', nrow(diamond))))
```
Residuals are given by $e$, in two vectors:
* first residual vector, just a fitted intercept on 1, so they are just variations around an average price
```{r}
lm(price ~ 1, data=diamond)
```
```{r}
mean(diamond$price)
```
* second residual vector, we add carat as a predictor variable, are variations around a regression line of price ~ carat.
```{r}
lm(price ~ carat, data=diamond)
```
The labelling for the plot is given by factor $fit$.
```{r}
ggplot(data.frame(e=e, fit=fit), aes(x=fit, y=e, fill=fit)) +
geom_dotplot(binaxis='y', stackdir='center', binwidth=30) +
xlab('fitting approach') +
ylab('residual price (SIN$)')
```
On the left side (red), we see the variation of prices around the average diamond prices.
On the right side (blue) we see the variation of prices around the regression line.
## Residual Variance
You can extract the standard variation of a fit using `$sigma`:
```{r}
fit <- lm(diamond$price ~ diamond$carat)
summary(fit)$sigma
```
Residual variance (variance of residuals) should also follow $\hat \sigma^2 = \dfrac{1}{(n - 2)} \sum_{i=1}^n e_i^2$, what when calculated:
```{r}
n <- length(diamond$price)
sqrt(sum(resid(fit)^2) / (n - 2))
```
Gives the exact same results.
This R function should give the exact same result:
```{r}
sqrt(deviance(fit)/(n-2))
```
## Comparing models with different combination of slope and intercept
```{r}
data(mtcars)
x <- mtcars$wt
y <- mtcars$mpg
```
Slope and intercept:
```{r}
sifit <- lm(y ~ x)
```
Only intercept
```{r}
ifit <- lm(y ~ 1)
```
Only slope
```{r}
sfit <- lm(y ~ x - 1)
```
What is the ratio of the error variability when comparing intercept only to intercept and slope, $\frac {intercept and slope}{intercept}$?
```{r}
sum(sifit$residuals^2)/sum(ifit$residuals^2)
```
## R Squared
```{r}
# mean of all Y
mu <- mean(galton$child)
# Centering data means subtracting the mean from each data point.
# Sum of the squares of the centered children's heights gives the total variation
sTot <- sum((galton$child - mu)^2)
fit <- lm(galton$child ~ galton$parent)
# deviance calculates the sum of the squares of the residuals.
# These are the distances between the children's heights and the regression line.
sRes <- deviance(fit)
r2 <- 1 - (sRes/sTot)
r2
```
What is the same as
```{r}
summary(fit)$r.squared
```
And since $R^2 = cor(x,y)^2$:
```{r}
cor(galton$child, galton$parent)^2
```
```{r, warning=FALSE, message=FALSE}
data("anscombe"); example("anscombe")
```
On all these examples we have a similar $R_2$, but the disposition of the data shows information is missing.
# Inference in Regression
Let's get back to the diamond data using mass to regress the price of diamonds:
```{r}
library(UsingR); data(diamond)
y <- diamond$price
x <- diamond$carat
n <- length(y)
```
## Coefficients Calculation
The hard way of doing it:
```{r}
beta1 <- cor(y, x) * sd(y)/sd(x)
beta0 <- mean(y) - beta1 * mean(x)
e <- y - beta0 - beta1 * x # residuals
sigma <- sqrt(sum(e^2) / (n-2)) # estimate of std deviation
ssx <- sum((x - mean(x))^2) # sums of squares of x's
seBeta0 <- (1 / n + mean(x)^2 / ssx) ^.5 * sigma
seBeta1 <- sigma / sqrt(ssx)
tBeta0 <- beta0 / seBeta0
tBeta1 <- beta1 / seBeta1
pBeta0 <- 2 * pt(abs(tBeta0), df=n-2, lower.tail=FALSE)
pBeta1 <- 2 * pt(abs(tBeta1), df=n-2, lower.tail=FALSE)
coefTable <- rbind(c(beta0, seBeta0, tBeta0, pBeta0),
c(beta1, seBeta1, tBeta1, pBeta1))
colnames(coefTable) <- c('Estimate', 'Std. Error', 't value', 'P(>|t|)')
rownames(coefTable) <- c('(Intercept)', 'x')
coefTable
```
The easy way to come up with the exact same values:
```{r}
fit <- lm(y ~ x)
summary(fit)$coefficients
```
Both steps produce the exact same results.
## Hypothesis Testing
```{r}
x <- c(0.61, 0.93, 0.83, 0.35, 0.54, 0.16, 0.91, 0.62, 0.62)
y <- c(0.67, 0.84, 0.6, 0.18, 0.85, 0.47, 1.1, 0.65, 0.36)
```
What is the p-value for the 2 sided hypothesis test if $\beta_1$ from a linear regression is 0 or not?
```{r}
fit <- lm(y ~ x)
summary(fit)$coef
```
The first row is $\beta_0$, second row is $\beta_1$ - so result is ~ 0.052964.
## Confidence Intervals
Now, if we want to produce confidence intervals
```{r}
library(UsingR); data(diamond)
y <- diamond$price
x <- diamond$carat
n <- length(y)
fit <- lm(y ~ x)
sumCoef <- summary(fit)$coefficients
```
95% confidence interval for $\beta_0$ (intercept):
```{r}
beta0Estimate <- sumCoef[1,1]
beta0StdError <- sumCoef[1,2]
beta0Estimate + c(-1,1) * qt(.975, df=fit$df) * beta0StdError
```
95% confidence interval for $\beta_1$ (slope):
```{r}
beta1Estimate <- sumCoef[2,1]
beta1StdError <- sumCoef[2,2]
beta1Estimate + c(-1,1) * qt(.975, df=fit$df) * beta1StdError
```
What this is basically stating is, with a 95% confidence, that a increase of 1 carat in mass will cause a diamond price to increase anything from SIN$ 3556.39 to SIN$ 3885.65
On cars, the mtcars data set, what is a 95% *confidence interval* for the expected mpg at the average weight?
```{r}
data(mtcars)
x <- mtcars$wt
y <- mtcars$mpg
fit <- lm(y ~ x)
predict(fit, data.frame(x=mean(x)), interval='confidence', level=0.95)
```
A new 3,000 pounds will be on sale soon. What is a 95% *prediction interval* of it's mpg consumption?
```{r}
predict(fit, data.frame(x=3.0), interval='prediction', level=0.95)
```
What is a 95% confidence interval for the *expected change* in mpg per 2,000 lbs increase in weight?
```{r}
fit <- lm(y ~ I(x/2)) # x/2 is x/2000 pounds since x is in 1000 pounds
sumCoef <- summary(fit)$coefficients
beta1Estimate <- sumCoef[2,1]
beta1StdError <- sumCoef[2,2]
beta1CI95 <- beta1Estimate + c(-1,1) * qt(.975, df=fit$df) * beta1StdError
beta1CI95
```
## Prediction
```{r}
library(UsingR); data(diamond)
y <- diamond$price
x <- diamond$carat
n <- length(y)
fit <- lm(y ~ x)
newx <- data.frame(x=seq(min(x), max(x), length=100))
p1 <- data.frame(predict(fit, newdata=newx, interval=('confidence')))
p2 <- data.frame(predict(fit, newdata=newx, interval=('prediction')))
p1$interval <- 'confidence'
p2$interval <- 'prediction'
p1$x <- newx$x
p2$x <- newx$x
dat <- rbind(p1, p2)
names(dat)[1] <- 'y'
```
```{r}
ggplot(dat, aes(x=x, y=y)) +
geom_ribbon(aes(ymin=lwr, ymax=upr, fill=interval), alpha=0.2) +
geom_line() +
geom_point(data=data.frame(x=x,y=y), aes(x=x,y=y), size=1, alpha=0.5)
```
# Multivariate Regression
## Experiment
```{r}
n <- 100
# predictors
x1 <- rnorm(n); x2 <- rnorm(n); x3 <- rnorm(n)
# outcome
y <- 1 + x1 + x2 + x3 + rnorm(n, sd=.1)
```
Calculating residuals for $Y$ and $X_1$:
```{r}
ey <- resid(lm(y ~ x2 + x3))
ex1 <- resid(lm(x1 ~ x2 + x3))
```
Calculating $\hat \beta_1$:
```{r}
sum(ey * ex1) / sum(ex1 ^ 2)
```
Same as:
```{r}
coef(lm(ey ~ ex1 - 1))
```
And should be the same if you add all regressors, looking under column x1:
```{r}
coef(lm(y ~ x1 + x2 + x3))
```
## Sample Analysys: Swiss Population Late 1800
We will start by a pairs plot:
```{r}
data(swiss)
my_fn <- function(data, mapping, method="loess", ...){
p <- ggplot(data = data, mapping = mapping) +
geom_point() +
geom_smooth(method=method, ...)
p
}
ggpairs(swiss, lower=list(continuous=my_fn))
```
Regress fertility as an outcome of all variables
```{r}
summary(lm(Fertility ~ ., data=swiss))$coefficients
```
Let's go over a few of these numbers one by one:
Agriculture Estimate -0.1721140 : we expect a .17 decrease on standardized fertility rates for every 1% of males involved in agriculture, holding the remanining variables constant.
Agriculture Std.Error 0.07030392: tells us how precise this estimate is. If we were to test $H_0 : \beta_{Agri} = 0$ versus $H_a : \beta{Agri} <> 0$ - we test against $\frac {estimate - \beta_{Agri}}{std error}$
Agriculture t value -2.448142: using $\beta_{Agri} = 0$ estimate divided by std error, -0.1721140/0.07030392
Agriculture Pr(>|t|) 1.872715e-02: probability of getting a t-statistic as extreme as t value
```{r}
summary(lm(Fertility ~ Agriculture, data=swiss))$coefficients
```
Coeficients are reversed when we remove all the other regressor variables. A few findings:
* The coeficient sign in Agriculture reverses itself with the inclusion of Examination and Education.
* Agricultural work is negatively correlated to educational attainment (-0.6395), while education and examination (correlation of 0.6984) are measuring equivalent things
* A causality claim between Agriculture and Fertility will be easily negated, all you have to do is to add more variables and the causality would be reversed or gone away.
What happens if you include an replicated/irrelevant regressor?
```{r}
z <- swiss$Agriculture + swiss$Education
lm(Fertility ~ . + z, data=swiss)
```
R responds back with a `NA` for z, meaning it is irrelevant to the model already in place.
## Factor Variables for Analysis
```{r}
data("InsectSprays")
head(InsectSprays)
```
```{r}
ggplot(data=InsectSprays, aes(y=count, x=spray, fill=spray)) +
geom_violin(colour='black', size=2) +
xlab('type of spray') + ylab('insect count')
```
Let's fit our model, using predictor as spray and count as the outcome
```{r}
summary(lm(count ~ spray, data=InsectSprays))$coef
```
You can see that SprayA is missing - that's becasue it hs been picked as the reference predictor.
A second example: using `mtcars`, fit a model with mpg as the outcome that includes number of cylinders as a factor variable and weight (wt) as confounder. Find the adjusted estimate for the expected change in mpg comparing 8 cylinders to 4.
```{r}
mtcars$cylf <- factor(mtcars$cyl)
fit <- lm(mpg ~ cylf + wt, mtcars)
summary(fit)$coef
```
The baseline in `(Intercept)` is the regressor factor 4 cylinders. Holding weight constant, the estimate for `cylf8` is relative to 4 cylinders, so the expected change is given by estimate of cylf8L: **-6.070860**
Now, how do estimates of mpg as outcome and cylinders as factor, holding weight constant and without weight? In other words, how does mpg vary in relation to cylinders, adjusted and not adjusted for weight?
```{r}
fitNotAdjusted <- lm(mpg ~ cylf, mtcars)
summary(fitNotAdjusted)$coef
```
If we compare coeficients of `fit` to `fitNotAdjusted` we are basically comparing the mpg rate when we keep weight constant (fit) to when we removed weight (fitNotAdjusted). The difference in mpg from 8 to 4 cylinders changed from **-6.070860** to **-11.563636** from coefficients on `fit` to `fitNotAdjusted`.
So, holding weight constant has less of an impact in mpg consumption than removing weight altogether.
Another test: would adding a regressor of an interaction between number of cylinders (as a factor) and weight have any significant effect in the prediction of the outcome mpg?
Let's first generate the new fit, adding a regressor of the interaction of wt and cylf (remember, interactions are recorded using the `*` operator):
```{r}
fitInteraction <- lm(mpg ~ wt + cylf + wt*cylf, mtcars)
summary(fitInteraction)$coef
```
What's the p-value for the likelihood ratio test comparing the two models, and should we reject the hypothesis using 0.05 as a type I error rate significance benchmark?
```{r}
anova(fit, fitInteraction)
```
Since the p-value is greater that 0.05 (our $\alpha$ for the benchmark), it would fail to reject the hypothesis (i.e. the interaction terms are not necessary)
### Estimates
* The estimate of 14.5 is the mean of sprayA (see the violin plot).
* Other estimates are the difference in means between sprayX and the reference predictor sprayA.
* The probability column is checking the probability of a sprayX being different from the reference sprayA.
* If you want to find a mean of a specific predictor you will have to add that to the reference predictor sprayA located in the intercept. For example for mean for sprayE:
```{r}
14.5000000 + -11.0000000
```
* If you have to compare means of other predictors, you will have to subtract one the other, for example - to compare means of sprayC and sprayF, the comparison would be sprayF - sprayC:
```{r}
2.1666667 -12.4166667
```
Note that this does not provide an error estimate.
### Fitting a curve by hand
You can fit the curve above
```{r}