Na dzisiejszych zajęciach opowiemy sobię trochę o wielokrotnej (wielorakiej) regresji liniowej (and. multiple linear regression). Pracować będziemy na przykładzie z rozdziału 15 podręcznika Howella, który znajduje się na stronie w materiałach dostępnych do pobrania po zalogowaniu. Proszę Państwa o przeczytanie tego rozdziału z podręcznika. Kod, który wklejam poniżej, ma stanowić bazę do ćwiczeń i ilustracje, jak różne rzeczy omówione w książce możemy zrobić w R. Kod będzie objaśniony, ale nie zastąpi (!) to lektury podręcznika. Dodatkowo pomyślałem, że możnaby przemycić trochę ciekawych i przydatnych R-owych bibliotek oraz technik, więc będę czasami korzystał z nieznanych Państwu funkcji, ale proszę się nie martwić – wszystkie będę objaśniał i tłumaczył co robią.
Na początek wczytajmy dwie biblioteki, których użyjemy do stworzenia tego pliku oraz dane znajdujące się w pliku Tab15-1.dat.
Biblioteka pander służy do ładnego wyświetlania wyników różnych testów statystycznych. Bez niej output różnych operacji, które wykonujemy, wygląda jak wydruk kodu źródłowego programu (szarawe tło oraz czcionka o stałej szerokości). Pander sprawia, że zamiast wydruku testy statystyczne zwracają ładnie sformatowane wyniki w formie np. tabelki. Z pakietu knitr będziemy używać funkcji kable, która w zasadzie służy do tego samego, czyli do ładnego wyświetlania danych w dokumentach HTML (takich jak ten). Od razu mogą Państwo zobaczyć działanie tego pakietu – dzięki funkcji kable nasza ramka danych jest estetycznie sformatowana.
Uwaga! Wczytaliśmy dane za pomocą funkcji read.table. Funkcja ta pozwala wczytać pliki, w których wartości oddzielone są białymi znakami (np. tabulatorami). Domyślnie jednak wczytuje pliki bez nagłówka (zakłada, że wszystkie wiersze to dane). My jednak ustawiliśmy argument header na TRUE, co sprawiło, że R potraktował pierwszy wiersz jako wiersz z nazwami kolumn.
Wczytane przez nas dane dotyczą edukacji w Stanach Zjednoczonych i zostały zebrane przez Gubner (1999). Jak widzimy, w każdym wierszu mamy informacje dotyczące jednego stanu.
Nas dzisiaj będą interesowały dane z kolumn SATcombined, PTratio, PctSAT, oraz LogPctSAT.
W kolumnie SATcombined znajduje się średni wynik testu SAT w danym stanie. Test ten umożliwia zarekrutowanie się na studia wyższe. Nie jest to jednak jedyny taki test. Uczniowie mogą również zdawać test ACT. Generalnie rzecz biorąc test SAT jest popularniejszy w jednych stanach, w innych zaś większą popularnością cieszy się ACT. Różnice w popularności możemy ocenić przyglądając się wartościom z kolumny PctSAT. Znajduje się tam odsetek uczniów, którzy przystąpili do egzaminu SAT. W kolumnie LogPctSAT znajdziemy logarytm naturalny z tej wartości. Dodatkowo warto pamiętać, że SAT wymagany jest przez wiele prestiżowych uczelni. W kolumnie PTratio znajdziemy informacje o tym ilu uczniów przypada na jednego nauczyciela. W kolumnie Expend znajdują się wydatki na edukacje w danym stanie.
Zanim przystąpimy do analizy danych, obejrzyjmy rozkład naszych zmiennych. Dla każdej z nich narysujemy histogram, wykres kwantyl-kwantyl (który posłuży nam do oceny normalności rozkładu) oraz wykres rozrzutu, gdzie zmienną na osi Y będzie SATcombined (oprócz samego SATcombined).
Żeby to zrobić, posłużymy się odpowiednimi funkcjami z pakietu ggplot2. Jeżeli nigdy nie korzystali Państwo z tego pakietu, to zachęcam do przerobienia odpowiedniego notebooka ze strony kursu (nagrałem też do nich filmiki, które dostępne są na YT). Dla tych z Państwa, którzy korzystali z tego pakietu, kilka ciekawych twistów:
Użyliśmy pakietu gridExtra i zawartej w nim funkcji grid.arrange, żeby narysować kilka wykresów stworzonych za pomocą ggplot2 na jednym panelu. Jesli rysowalibyśmy te wykresy używając standardowych funkcji R takich jak hist, to moglibyśmy po prostu użyć par(mfrow=c(4,3)). W przypadku ggplot2 technika ta jednak nie działa.
Kazdy z wykresów jest obiektem, który można przypisać do zmiennej, co zrobiliśmy.
Wszystkie te obiekty przekazaliśmy do funkcji grid.arrange, która narysowała te wykresy.
To, w jaki sposób rysuje się zawarte poniżej typy wykresów w ggplot2, omówione jest w notatniku poświęconym temu pakietowi, więc odsyłam do niego (oraz do dokumentacji ggplot2!), jeżeli ktoś chciałby dowiedzieć się więcej.
`geom_smooth()` using formula = 'y ~ x'
`geom_smooth()` using formula = 'y ~ x'
`geom_smooth()` using formula = 'y ~ x'
`geom_smooth()` using formula = 'y ~ x'
Rzeczą, która powinna zwrócić naszą uwagę jest to, że relacja między Expend i SATCombined jest negatywna, to znaczy im więcej pieniędzy wydajemy na edukacje, tym gorsze wyniki uzyskują uczniowie (sic!). Jest to dość kontrintuicyjne, ponieważ spodziewalibysmy się zupełnie odwrotnego efektu – wydatki na edukacje powinny przecież polepszać jej jakość.
Spróbumy teraz obliczyć współczynnik korelacji, między zmiennymi, które nas interesują. Jak Państwo wiedzą, do obliczenia współczynnika korelacji oraz przeprowadzania odpowiedniego testu statystyznego (\(H_0: \rho = 0\)) używamy funkcji cor.test. Dla przykładu możemy obliczyć korelację między zmienną SATcombined oraz Expend:
pander(cor.test(~ SATcombined + Expend, data = data))
Pearson’s product-moment correlation: SATcombined and Expend
Test statistic
df
P value
Alternative hypothesis
cor
-2.851
48
0.006408 * *
two.sided
-0.3805
Widzimy, że uzyskaliśmy negatywny współczynnik korelacji — niezbyt wysoki, ale statystycznie istotny! Jest to dość zaskakujące.
Efekt ten, przynajmniej według podręcznika, z którego pochodzi ten przykład, związany jest z faktem, że w tych stanach, w których mały odsetek uczniów przystępuje do testu SAT, przystępują do niego zazwyczaj najlepsi i to zaburza wynik. W dalszej części notatnika pokażemy w jaki sposób możemy za pomocą wielokrotnej regresji to pokazać!
Krótka uwaga na marginesie. Gdybyśmy mieli policzyć współczynnik korelacji dla wszystkich kombinacji zmiennych, musielibyśmy napisać bardzo dużo kodu! Możemy sobie z tym jednak poradzić. W pakiecie rstatix znajduje się sporo ciekawych funkcji do ,,masowego’’ przeprowadzania testów statystycznych. My skorzystamy z funkcji cor_test (która jest odpowiednikiem cor.test z biblioteki standardowej R).
library(rstatix)# Do funkcji cor_test przekazujemy ramkę danych oraz nazwy kolumn.results <-cor_test(data = data, Expend, PTratio, Salary, PctSAT, SATcombined, LogPctSAT)# Dane wyjściowe `cor_test` to ramka danych więc możemy ją sformatować za pomocą `kable`kable(results[, c("var1", "var2", "cor", "p")])
var1
var2
cor
p
Expend
Expend
1.0000
0.0000000
Expend
PTratio
-0.3700
0.0079873
Expend
Salary
0.8700
0.0000000
Expend
PctSAT
0.5900
0.0000058
Expend
SATcombined
-0.3800
0.0064080
Expend
LogPctSAT
0.5600
0.0000227
PTratio
Expend
-0.3700
0.0079873
PTratio
PTratio
1.0000
0.0000000
PTratio
Salary
-0.0011
0.9936975
PTratio
PctSAT
-0.2100
0.1374041
PTratio
SATcombined
0.0810
0.5748329
PTratio
LogPctSAT
-0.1300
0.3610337
Salary
Expend
0.8700
0.0000000
Salary
PTratio
-0.0011
0.9936975
Salary
Salary
1.0000
0.0000000
Salary
PctSAT
0.6200
0.0000018
Salary
SATcombined
-0.4400
0.0013913
Salary
LogPctSAT
0.6100
0.0000022
PctSAT
Expend
0.5900
0.0000058
PctSAT
PTratio
-0.2100
0.1374041
PctSAT
Salary
0.6200
0.0000018
PctSAT
PctSAT
1.0000
0.0000000
PctSAT
SATcombined
-0.8900
0.0000000
PctSAT
LogPctSAT
0.9600
0.0000000
SATcombined
Expend
-0.3800
0.0064080
SATcombined
PTratio
0.0810
0.5748329
SATcombined
Salary
-0.4400
0.0013913
SATcombined
PctSAT
-0.8900
0.0000000
SATcombined
SATcombined
1.0000
0.0000000
SATcombined
LogPctSAT
-0.9300
0.0000000
LogPctSAT
Expend
0.5600
0.0000227
LogPctSAT
PTratio
-0.1300
0.3610337
LogPctSAT
Salary
0.6100
0.0000022
LogPctSAT
PctSAT
0.9600
0.0000000
LogPctSAT
SATcombined
-0.9300
0.0000000
LogPctSAT
LogPctSAT
1.0000
0.0000000
Przejdźmy teraz do głównego tematu dzisiejszych zajęć, to znaczy do wielorakiej regresji liniowej. Jak już wspomnieliśmy, chcielibyśmy zobaczyć związek między wydatkami na szkolnictwo i testem SAT kontrolując przy tym odsetek przystępujących do SAT uczniów, to znaczy zmienną LogPctSAT (logarytm z odsetka przystępujących osób, wybraliśmy go bo ma troszkę lepszy rozkład i zalezność jest bardziej liniowa).
Stworzymy dwa modele w których zmienną objaśnianą jest SATcombined. W pierwszym z nich (fit1) uwzględniać będziemy tylko Expend.
fit1 <-lm(SATcombined ~ Expend, data = data)pander(summary(fit1))
Estimate
Std. Error
t value
Pr(>|t|)
(Intercept)
1089
44.39
24.54
8.168e-29
Expend
-20.89
7.328
-2.851
0.006408
Fitting linear model: SATcombined ~ Expend
Observations
Residual Std. Error
\(R^2\)
Adjusted \(R^2\)
50
69.91
0.1448
0.127
Teraz stworzymy drugi model, w którym to uwzględnimy jednak dodatkową zmienną - LogPctSAT.
fit2 <-lm(SATcombined ~ Expend + LogPctSAT, data = data)pander(summary(fit2))
Estimate
Std. Error
t value
Pr(>|t|)
(Intercept)
1147
16.7
68.68
8.447e-49
Expend
11.13
3.264
3.409
0.001346
LogPctSAT
-78.2
4.471
-17.49
3.292e-22
Fitting linear model: SATcombined ~ Expend + LogPctSAT
Observations
Residual Std. Error
\(R^2\)
Adjusted \(R^2\)
50
25.78
0.8861
0.8813
Widzimy, że zmiana jest gigantyczna! W poprzednim wypadku współczynnik regresji był dla Expand ujemny (\(-20.89\)) ale teraz, kiedy kontrolujemy zmienną LogPctSAT jest delikatnie dodatni (\(11.13\)). To jest dokładnie to, czego oczekiwaliśm! Relacja między LogPctSAT a SATcombined jest negatywna - im mniej osób przystępuje w danym stanie do egzaminu, tym wyższy wynik średnio uzyskują. To również jest zgodne z naszymi oczekiwaniami. Warto zwrócić uwagę, że dramatycznie zwiększyło się również dopasowanie naszego modelu do danych - współczynnik \(R^2\) wzrósł z \(0.145\) do \(0.886\).
Interpretacja wielokrotnej regresji
Spróbujmy prześledzi, co tak naprawdę robi wielokrotna regresja liniowa po to, aby zrozumieć jak interpretować jej wyniki.
Stwórzmy model, w którym zmienną objaśnianą będzie SATcombined a predyktorem LogPctSAT.
fit_sat <-lm(SATcombined ~LogPctSAT, data = data)
Obliczmy jakie wartości dla SATcombined przewiduje nasz model. Posłużymy się tutaj funkcją predict. Działa ona tak, jakbyśmy po prostu wzięli wyraz wolny regresji oraz współczynniki kierunkowe a następnie dla każdej obserwacji obliczali przewidywaną wartość.
predictsat <-predict(fit_sat)
Następnie obliczmy różnicę między prawdziwymi (rzeczywiście zaobserwowanymi) wartościami a wartościami przewidywanymi przez regresje (czyli residua/reszty!). Przypiszmy je do zmiennej residsat.
residsat <- data$SATcombined - predictsat
W tym momencie musimy dokonać waznej obserwacji. Wartości naszej nowej zmiennej (residsat) są nieskorelowane z LogPctSAT w naszej próbie — usunęliśmy z nich liniowy związek z tą zmienną. Dokładnie to samo możemy zrobić z naszą drugą zmienną, czyli Expend.
Mamy teraz dwie zmienne, które są nieskorelowane z LogPctSAT w naszej próbie. W takim razie, możemy stworzyć model, w którym przewidujemy wartości residsat na podstawie wartości residexpend!
Jak widać współczynnik regresji który uzyskaliśmy dla tego modelu z jedną zmienną jest dokładnie taki sam jak wóœczas, gdy mieliśmy dwie zmienne. Dlaczego? Dlatego, że ,,manualnie’’ zrobiliśmy to, co regresja robi za nas – obliczyliśmy współczynnik regresji kontrolując efekty, które można przypisać trzeciej zmiennej (bo ,,usunęliśmy’’ te efekty zarówno z predyktora jak i ze zmiennej objaśnianej).
O wielokrotnej regresji liniowej możemy też myśleć w inny sposób. Wiemy, że w przypadku naszego modelu z dwoma predyktorami równanie regresji ma postać
\[
\hat{Y} = b_1X_1 + b_2X_2 + b_0
\] Czyli umując to w kategoriach naszych zmiennych:
Możemy więc korzystając z tego wzoru obliczyć \(\widehat{SAT}\).
predictions <-predict(fit2)
Obliczmy więc korelację między \(\widehat{SAT}\) (naszymi predykcjami w zmiennej predictions) oraz \(SAT\) (czyli wartościami zaobserwowanymi). Tak obliczony współczynnik korelacji podnieśmy do kwadratu.
Przypomnijmy sobie jak wyglądał nasz model dla dwóch zmiennych, który stworzyliśmy wczesniej.
pander(summary(lm(SATcombined ~ Expend + LogPctSAT, data = data)))
Estimate
Std. Error
t value
Pr(>|t|)
(Intercept)
1147
16.7
68.68
8.447e-49
Expend
11.13
3.264
3.409
0.001346
LogPctSAT
-78.2
4.471
-17.49
3.292e-22
Fitting linear model: SATcombined ~ Expend + LogPctSAT
Observations
Residual Std. Error
\(R^2\)
Adjusted \(R^2\)
50
25.78
0.8861
0.8813
Jak widzimy uzyskaliśmy dokładnie tę samą wartość co w przypadku \(R^2\) wcześniej! Nakierowuje nas to na pewien sposób myślenia o regresji, zgodnie z którym zasadniczo sprowadza się ona do utworzenia nowej zmiennej (\(\widehat{SAT}\)), będącej najlepszą liniową kombinacją predyktorów w naszym modelu (Expend oraz LogPctSAT). Przez ,,najlepszą liniową kombinację’’ rozumiemy to, że nie ma żadnych innych wag, które moglibyśmy przypisać naszym predyktorom (współczynników regresji), które lepiej przewidywałyby naszą zmienną objaśnianą.
O współczynniku \(R\) dla wielokrotnej regresji liniowej możemy myśleć po prostu jako o współczynniku korelacji \(r\) Pearsona tyle że dla zmiennej stanowiącej najlepszą liniową kombinację predyktorów.