Übungszettel als PDF-Datei zum Drucken
Übungszettel mit Lösungen
Lösungszettel als PDF-Datei zum Drucken
Der gesamte Übugszettel als .Rmd-Datei (Zum Downloaden: Rechtsklick > Speichern unter…)
Bitte beantworten Sie die Fragen in einer .Rmd Datei. Sie können Sie über Datei > Neue Datei > R Markdown...
eine neue R Markdown Datei erstellen. Den Text unter dem Setup Chunk (ab Zeile 11) können Sie löschen. Unter diesem Link können Sie auch unsere Vorlage-Datei herunterladen.
Informationen, die Sie für die Bearbeitung benötigen, finden Sie auf der Website der Veranstaltung
Zögern Sie nicht, im Internet nach Lösungen zu suchen. Das effektive Suchen nach Lösungen für R-Probleme im Internet ist tatsächlich eine sehr nützliche Fähigkeit, auch Profis arbeiten auf diese Weise. Die beste Anlaufstelle dafür ist der R-Bereich der Programmiererplattform Stackoverflow
Auf der Website von R Studio finden Sie sehr hilfreiche Übersichtszettel zu vielen verschiedenen R-bezogenen Themen. Ein guter Anfang ist der Base R Cheat Sheet
Da es sich um eine praktische Übung handelt, können wir Ihnen nicht alle neuen Befehle einzeln vorstellen. Stattdessen finden Sie hier Verweise auf sinnvolle Ressourcen, in denen Sie für die Bearbeitung unserer Aufgaben nachschlagen können.
Ressource | Beschreibung |
---|---|
Field, Kapitel 7 (7.1 - 7.5, 7.9) | Buchkapitel, das Schritt für Schritt erklärt, worum es geht, und wie man Regressionen in R durchführt. Große Empfehlung! |
R for Data Science | Einsteiger-Buch von R-Gott Hadley Wickham. Hier wird topaktuell in die Arbeit mit R, insbesondere zur Datenaufbereitung und Visualisierung, eingeführt. |
R Tutorial | Schritt-für-Schritt Einführung in das Arbeiten mit R von Christian Treffenstädt. Nützlich, falls Sie grundlegende Dinge noch einmal nachschlagen möchten |
Mit strg
+ alt
+ c
(Windows) oder cmd
+ alt
+ c
(Mac) können Sie direkt den Code-Chunk ausführen, in dem sich Ihr Cursor gerade befindet. Mit strg
+ alt
+ n
(Windows) oder cmd
+ alt
+ n
(Mac) führen Sie direkt den nächsten Chunk aus.
Setzen Sie ein sinnvolles Arbeitsverzeichnis für den Übungszettel (in der Regel der Ordner, in dem Ihre .Rmd liegt). Aber Vorsicht: Beim Rendern (Knit) geht RStudio davon aus, dass das Working-Directory das ist, in dem auch die .Rmd-Datei liegt. Dies ist besonders wichtig, wenn es um relative Links geht.
Laden Sie den Datensatz starwars.csv herunter (Rechtsklick > Ziel speichern unter oder Rechtsklick > Verknüpfte Datei laden) und speichern Sie ihn in Ihrem Arbeitsverzeichnis (idealerweise haben Sie noch den Ordner vom letzten Übungszettel - speichern Sie den Datensatz im Unterordner /data).
Laden Sie die Pakete des tidyverse
und fügen Sie eine entsprechende Code-Zeile an den Beginn Ihres Dokuments ein.
Lesen Sie den Datensatz starwars.csv
unter dem Namen sw_data
in R ein.
Bitte folgen Sie den Anweisungen im Aufgabentext.
Bitte folgen Sie den Anweisungen im Aufgabentext.
library(tidyverse)
Anmerkung: library()
und require()
sind beides Befehle zum Laden von Paketen. require()
ist prinzipiell für die Verwendung innerhalb von Funktionen gedacht. Siehe ?library
oder ?require
für Details.
# example code, works only if the local situation permits ...
# sw_data <- read_csv("data/starwars.csv")
# alternative reading from URL
sw_data <- readr::read_csv("https://md.psych.bio.uni-goettingen.de/mv/data/div/starwars.csv")
##
## ── Column specification ──────────────────────────────────────────────────────────────────────────────
## cols(
## name = col_character(),
## height = col_double(),
## mass = col_double(),
## hair_color = col_character(),
## skin_color = col_character(),
## eye_color = col_character(),
## birth_year = col_double(),
## gender = col_character(),
## homeworld = col_character(),
## species = col_character()
## )
Schlagen Sie für Erklärungen zur Verwendung von lm()
in Kapitel 7.4.2 und zur Interpretation des Outputs in Kapitel 7.5 von Discovering Statistics Using R (Field, 2012) nach.
Erstellen Sie ein Regressions-Modell namens m_height
, in dem Sie das Gewicht durch die Größe der Personen im Datensatz vorhersagen. Nutzen Sie dafür die FUnktion lm()
.
Lassen Sie sich eine Zusammenfassung der Analyse mit summary()
anzeigen.
Schreiben Sie mit den Werten aus dem Output aus summary()
die Regressionsgleichung auf.
Interpretieren Sie die Regression
m_height <- lm(mass ~ height, data = sw_data)
summary(m_height)
##
## Call:
## lm(formula = mass ~ height, data = sw_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -61.43 -30.03 -21.13 -17.73 1260.06
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -13.8103 111.1545 -0.124 0.902
## height 0.6386 0.6261 1.020 0.312
##
## Residual standard error: 169.4 on 57 degrees of freedom
## (28 observations deleted due to missingness)
## Multiple R-squared: 0.01792, Adjusted R-squared: 0.0006956
## F-statistic: 1.04 on 1 and 57 DF, p-value: 0.312
Die Allgemeine Form für die Regressionsgleichung kann man z.B. so schreiben: \[y_i = \beta_0 + \beta_1 \cdot x_i + \epsilon_i\] Wir können mit unserem Modell nicht die wahren Werte von \(\beta_0\) und \(\beta_1\) bestimmen, sondern sie nur anhand unserer Daten schätzen. Deshalb gibt es eine extra Gleichung für die Schätzer:
\[\hat{y}_i = \hat{\beta}_0 + \hat{\beta}_1 \cdot x_i\] Das Dach über den Buchstaben gibt an, dass es sich hier im geschätzte Werte handelt. In der Schätzgleichung, wenn \(\hat{y}_i\) auf der linken Seite steht, brauchen wir außerdem kein \(\epsilon_i\) mehr, denn das Residuum \(\epsilon_i\) ist der Unterschied zwischen \(y_i\) und \(\hat{y}_i\), also zwischen vorhergesagtem, geschätztem Outcome und tatsächlichem Outcome.
Jetzt können wir die Werte aus unserem Output von summary()
in die Gleichung oben eintragen. \(\hat{\beta}_0\) ist der Intercept, \(\hat{\beta}_1\) ist der Koeffizient für den Prädiktor Größe (height
).
\[\widehat{mass}_i = -13.81 + 0.64 \cdot height_i\] Wenn wir nicht das vorhergesagte, geschätzte Gewicht \(\widehat{mass}_i\), sondern das echte, gemessene Gewicht \(mass_i\) auf die linke Seite schreiben, dann fügen wir wieder das Residuum hinzu:
\[mass_i = -13.81 + 0.64 \cdot height_i + \epsilon_i\] Beide Schreibweisen sind legitim.
Relevant ist hier der F-Test am Ende der Ausgabe von summary()
. In diesem Fall wird der Test nicht signifikant mit \(F(1, 57) = 1.04\) und \(p = 0.312\). Das heißt, das Modell passt nicht signifikant besser auf die Daten als eines, das nur das mittlere Gewicht der Personen im Datensatz zur Vorhersage benutzt. Das ist das sogenannte Nullmodell, es wird immer als Vergleichspunkt für diesen F-Test genommen.
Relevant ist hier der t-Test für den Koeffizienten des Prädiktors “Größe” (height
) im Output von summary()
. Der Test wird hier nicht signifikant mit \(t(57) = 1.02\) und \(p = 0.312\). Das heißt, der Regressionskoeffizient für Größe ist nicht signifikant verschieden von 0.
mass
). Hinweis: Die Werte in mass
sind in Kilogramm angegeben.# Objekt erstellen
height_plot <- ggplot(sw_data, aes(x = height, y = mass))
# Ebene hinzufügen und direkt mit abspeichern
height_plot <- height_plot + geom_point()
# Plot anzeigen
height_plot
## Warning: Removed 28 rows containing missing values (geom_point).
# Ebene hinzufügen und direkt mit abspeichern
height_plot <- height_plot + geom_smooth(method = "lm", se = F)
# Plot anzeigen
height_plot
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 28 rows containing non-finite values (stat_smooth).
## Warning: Removed 28 rows containing missing values (geom_point).
# Ebene hinzufügen und direkt mit abspeichern
height_plot <- height_plot +
labs(title = "Größe und Gewicht im Star Wars-Universum",
x = "Größe in cm",
y = "Gewicht in kg")
# Plot anzeigen
height_plot
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 28 rows containing non-finite values (stat_smooth).
## Warning: Removed 28 rows containing missing values (geom_point).
Hinweis: Ein anderes Theme kann hier auch richtig sein. theme_classic()
entspricht meinem Eindruck nach am ehesten den APA-Vorgaben.
# Ebene hinzufügen und direkt mit abspeichern
height_plot <- height_plot + theme_classic()
# Plot anzeigen
height_plot
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 28 rows containing non-finite values (stat_smooth).
## Warning: Removed 28 rows containing missing values (geom_point).
Hier beachten: Ich habe oben bei den Lösungen in jeder Unteraufgabe den Plot mit der neuen Ebene abgespeichert. Deshalb kann ich nun einfach das Objekt height_plot
hier verwenden, um das Bild abzuspeichern.
ggsave("height_plot.png", height_plot)
Hier noch einmal der komplette Code für den Plot:
# Objekt erstellen
height_plot <- ggplot(sw_data, aes(x = height, y = mass))
# Ebenen hinzufügen und abspeichern
height_plot <- height_plot +
geom_point() +
geom_smooth(method = "lm", se = F) +
labs(title = "Größe und Gewicht im Star Wars-Universum",
x = "Größe in cm",
y = "Gewicht in kg") +
theme_classic()
Der Plot erzeugt einen Verdacht: Wird die Regression von einem einzigen Extremwert verzerrt? Wir wollen dem weiter auf den Grund gehen.
Wenden Sie die Funktion plot()
auf das Regressionsmodell an, das Sie oben erzeugt haben. Folgen Sie nun den Anweisungen in der Konsole. Dort sollten Sie die Aufforderung “Drücke Eingabetaste für den nächsten Plot:” sehen. Insgesamt werden Ihnen nacheinander vier Plots angezeigt.
Lesen Sie diesen kurzen Artiekl. Finden Sie die folgenden Dinge für jeden Plot heraus:
Schauen Sie sich nun noch einmal die vier Plots an. Was fällt Ihnen auf?
Identifizieren Sie, zu welcher Person die auffällige Beobachtung gehört. (Hinweis: In den diagnostischen Plots steht neben Extremwerten in der Regel die zugehörige Zeile im Datensatz.)
plot(m_height)
Alternativ zur Darstellung aller Plots auf einmal:
par(mfrow = c(2,2))
plot(m_height)
In jedem einzelnen Plot fällt Beobachtung Nr. 16 aus der Reihe. Die anderen Werte sehen gut aus, nur diese Beobachtung scheint stark abzuweichen.
Da wir wissen, dass es sich um Beobachtung, also Zeile Nr. 16 handelt, können wir einfach mit eckigen Klammern hinter dem Namen des tibbles nachsehen, was in dieser Zeile steht.
Beachten: Wenn wir nur eine Zeile auswählen wollen, müssen wür trotzdem das Schema [<zeile>, <spalte>]
einhalten. Das heißt, wir müssen das Komma setzen! Den Wert für die Spalte können wir leer lassen. So bekommen wir z.B. alle Spalten, die in die Konsole passen, für die Zeile 16 ausgegeben.
sw_data[16,]
## # A tibble: 1 x 10
## name height mass hair_color skin_color eye_color birth_year gender homeworld species
## <chr> <dbl> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr> <chr>
## 1 Jabba Desili… 175 1358 <NA> green-tan, b… orange 600 hermaphr… Nal Hutta Hutt
Jabba scheint hier also für Probleme verantwortlich zu sein. Ein Blick in seine Daten zeigt, dass das Sinn macht: Bei einer Körpergröße von 1,75m wiegt er 1,358 Tonnen.
Erstellen Sie eine Kopie von sw_data
namens sw_data_ex
, in der Sie den problematischen Fall ausschließen, den Sie oben identifiziert haben.
Führen Sie erneut eine Regressionsanalyse durch und lassen Sie sich den Output mit summary()
anzeigen.
Erstellen Sie, wie oben, einen Scatterplot mit Regressionslinie, basierend auf den neuen Daten. (Tipp: Sie können hier sehr viel Code wiederverwenden.)
Vergleichen Sie die erste und die zweite Regressionsanalyse in Bezug auf
Interpretieren Sie die Ergebnisse der Analyse.
Wir können zum Beispiel die Funktion filter()
für diesen Zweck benutzen. Dafür finde ich hier zunächst den genauen Namen der betroffenen Person heraus. Mit eckigen Klammern hinter dem Namen des tibble-Datensatzes kann ich Zeilen und spalten auswählen. Das funktioniert nach dem Muster <tibble>[<zeile>, <spalte>]
.
sw_data[16,1]
## # A tibble: 1 x 1
## name
## <chr>
## 1 Jabba Desilijic Tiure
Jetzt kenne ich den vollen Namen und kann ihn in der filter()
Funktion einsetzen. Ich benutze name != "Jabba Desilijic Tiure"
, um mir nur die Beobachtungen (Zeilen) anzeigen zu lassen, bei denen der Name ungleich (dafür steht !=
) Jabba Desilijic Tiure ist.
sw_data_ex <- sw_data %>% filter(name != "Jabba Desilijic Tiure")
Modell erstellen
m_height_ex <- lm(mass ~ height, data = sw_data_ex)
Output anzeigen
summary(m_height_ex)
##
## Call:
## lm(formula = mass ~ height, data = sw_data_ex)
##
## Residuals:
## Min 1Q Median 3Q Max
## -39.382 -8.212 0.211 3.846 57.327
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -32.54076 12.56053 -2.591 0.0122 *
## height 0.62136 0.07073 8.785 4.02e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 19.14 on 56 degrees of freedom
## (28 observations deleted due to missingness)
## Multiple R-squared: 0.5795, Adjusted R-squared: 0.572
## F-statistic: 77.18 on 1 and 56 DF, p-value: 4.018e-12
Ich ändere hier im Vergleich zum Code von oben nur… 1. … den Namen, unter dem das Objekt gespeichert wird. 2. … den verwendeten Datensatz (sw_data_ex
) 3. … den Untertitel, der vorher nicht vergeben war. Hier gibt er an, dass der Plot die Daten von Jabba nicht enthält.
# Objekt erstellen
height_plot_ex <- ggplot(sw_data_ex, aes(x = height, y = mass))
# Ebenen hinzufügen und Plot anzeigen
height_plot_ex +
geom_point() +
geom_smooth(method = "lm", se = F) +
labs(title = "Größe und Gewicht im Star Wars-Universum",
subtitle = "Ohne Jabba",
x = "Größe in cm",
y = "Gewicht in kg") +
theme_classic()
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 28 rows containing non-finite values (stat_smooth).
## Warning: Removed 28 rows containing missing values (geom_point).
Hierfür stellen wir am besten die beiden Outputs gegenüber:
summary(m_height) # Modell mit Jabba
##
## Call:
## lm(formula = mass ~ height, data = sw_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -61.43 -30.03 -21.13 -17.73 1260.06
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -13.8103 111.1545 -0.124 0.902
## height 0.6386 0.6261 1.020 0.312
##
## Residual standard error: 169.4 on 57 degrees of freedom
## (28 observations deleted due to missingness)
## Multiple R-squared: 0.01792, Adjusted R-squared: 0.0006956
## F-statistic: 1.04 on 1 and 57 DF, p-value: 0.312
summary(m_height_ex) # Modell ohne Jabba
##
## Call:
## lm(formula = mass ~ height, data = sw_data_ex)
##
## Residuals:
## Min 1Q Median 3Q Max
## -39.382 -8.212 0.211 3.846 57.327
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -32.54076 12.56053 -2.591 0.0122 *
## height 0.62136 0.07073 8.785 4.02e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 19.14 on 56 degrees of freedom
## (28 observations deleted due to missingness)
## Multiple R-squared: 0.5795, Adjusted R-squared: 0.572
## F-statistic: 77.18 on 1 and 56 DF, p-value: 4.018e-12
Vergleich | Mit Jabba | Ohne Jabba |
---|---|---|
\(R^2\) | \(0.018\) | \(0.589\) |
F-Test | \(F(1,57) = 1.04\), \(p = 0.312\) | \(F(1, 56) = 77.18\), \(p < .001\) |
t-Test für \(\hat{\beta}_1\) | \(t(57)=1.02\), \(p = 0.312\) | \(t(56)=8.79\), \(p < .001\) |
Wichtig ist hier die Unterscheidung zwischen explorativen und konfirmatorischen Ergebnissen. Da wir in unseren Analysen keine vorher definierten Hypothesen festgelegt haben, handelt es sich um explorative Ergebnisse. Diese können wir benutzen, um neue Hypothesen zu generieren, die wir dann in der Folge mit weiteren Experimenten überprüfen. Erst wenn sich in solchen, konfirmatorischen Studien die vorhergesagten Ergebnisse zeigen, liegt starke Evidenz für eine Hypothese oder Theorie vor.
Zunächst einmal wird offensichtlich, dass Jabba ein besonderer Fall ist, für den keine ähnliche Beziehung zwischen Größe und Gewicht gilt, wie für die anderen Charaktere im Datensatz.
Wir könnten daraus z.B. die Hypothese ableiten, dass auch die Spezies ein wichtiger Faktor für das Gewicht eines Individuums ist. Diese Hypothese könnten wir in der Folge durch die Erhebung neuer Daten konfirmatorisch testen.
Aus der Regressionsanalyse ohne Jabba können wir die Hypothese ableiten, dass für viele Charaktere im Star Wars Universum eine enge Beziehung zwischen Größe und Gewicht besteht, die es uns erlaubt, das Gewicht aufgrund der Größe vorherzusagen. Wir könnten nun weitere Daten erheben, um diese explorativen Ergebnisse konfirmatorisch zu untersuchen.
Anmerkung: Diese Übungszettel basieren zum Teil auf Aufgaben aus dem Lehrbuch Dicovering Statistics Using R (Field, Miles & Field, 2012). Sie wurden für den Zweck dieser Übung modifiziert, und der verwendete R-Code wurde aktualisiert.
Field, A., Miles, J., & Field, Z. (2012). Discovering Statistics Using R. London: SAGE Publications Ltd.
Exercise sheet with solutions included
Exercise sheet with solutions included as PDF
The source code of this sheet as .Rmd (Right click and “store as” to download …)
Please give your answers in a .Rmd file. You may generate one from scratch using the file menu: ‘File > new file > R Markdown …’ Delete the text below Setup Chunk (starting from line 11). Alternatively you may use this sample Rmd by donloading it.
You may find the informations useful that you can find on the start page of this course.
Don’t hesitate to google for solutions. Effective web searches to find solutions for R-problems is a very useful ability, professionals to that too … A really good starting point might be the R area of the programmers platform Stackoverflow
You can find very useful cheat sheets for various R-related topics. A good starting point is the Base R Cheat Sheet.
This is a hands on course. We cannot present you all the useful commands in detail. Instead we give you links to useful ressources, where you might find hints to help you with the exercises.
Ressource | Description |
---|---|
Field, Chapter 7 (7.1 - 7.5, 7.9) | Book chapter with a step for step introduction to simple regression and how to do it in R. Recommendation! |
R for Data Science | Textbook with an introduction to R |
Peters Simple Regression Pages | Peters unit on simple regression. A resource to find running examples. |
R Tutorial | A step by step introduction to working with R. authored by Christian Treffenstädt. Useful as a reference for basic stuff. |
You can run directly the code chunk, where your cursor is currently in by using shortcut: strg
+ alt
+ c
(Windows) or cmd
+ alt
+ c
(Mac). You can run the following chunk with: strg
+ alt
+ n
(Windows) or cmd
+ alt
+ n
(Mac).
tidyverse
are loaded. Insert a code line for that in the beginning of your Rmd-file.starwars.csv
and store it as a data object named sw_data
.Please follow the recommendation of the exercise text.
# library(tidyverse)
# or better
require(tidyverse)
Annotation: library()
and require()
are both commands to load packages. Require is used often inside functions, as it outputs a warning and continues if the package is not found, whereas library will throw an error. See ?library
or ?require
for details.
# syntax would be
# sw_data <- read_csv("data/starwars.csv")
# alternative reading from URL, independent from local situation
sw_data <- readr::read_csv("https://md.psych.bio.uni-goettingen.de/mv/data/div/starwars.csv")
##
## ── Column specification ──────────────────────────────────────────────────────────────────────────────
## cols(
## name = col_character(),
## height = col_double(),
## mass = col_double(),
## hair_color = col_character(),
## skin_color = col_character(),
## eye_color = col_character(),
## birth_year = col_double(),
## gender = col_character(),
## homeworld = col_character(),
## species = col_character()
## )
lm()
and chapter 7.5 for the interpretation of the results.m_height
where you predict mass by height. Use function lm()
for that.summary()
.m_height <- lm(mass ~ height, data = sw_data)
summary(m_height)
##
## Call:
## lm(formula = mass ~ height, data = sw_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -61.43 -30.03 -21.13 -17.73 1260.06
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -13.8103 111.1545 -0.124 0.902
## height 0.6386 0.6261 1.020 0.312
##
## Residual standard error: 169.4 on 57 degrees of freedom
## (28 observations deleted due to missingness)
## Multiple R-squared: 0.01792, Adjusted R-squared: 0.0006956
## F-statistic: 1.04 on 1 and 57 DF, p-value: 0.312
We can write a more general form of a regression equation like this:
\[y_i = \beta_0 + \beta_1 \cdot x_i + \epsilon_i\] We cannot calculate the true values of \(\beta_0\) and \(\beta_1\) but we can estimate them using our data. Therefore we have a separate equation for the estimators:
\[\hat{y}_i = \hat{\beta}_0 + \hat{\beta}_1 \cdot x_i\] The hat ^
above the letters means, that the values are estimated. In the equation where we estimate \(\hat{y}_i\) (put left) we do not need \(\epsilon_i\) because the residuum \(\epsilon_i\) is the difference between \(y_i\) und \(\hat{y}_i\) and thus the difference between estimated outcome and real outcome.
We can now insert the values of our summary()
into the equation above. \(\hat{\beta}_0\) is the intercept, \(\hat{\beta}_1\) is the coefficient for predictor height (height
).
\[\widehat{mass}_i = -13.81 + 0.64 \cdot height_i\] If we don’t put the predicted weight \(\widehat{mass}_i\) at the left side of the equation but the real weight \(mass_i\) we have to add the residuals also:
\[mass_i = -13.81 + 0.64 \cdot height_i + \epsilon_i\] Both posibilities are o.k.
The F-Test at the end of the summary()
is relevant. In our case the test with \(F(1, 57) = 1.04\) and \(p = 0.312\) doesn’t reach the usual significance level of 5%. This means that our model cannot predict the data better than a model that only uses the mean as a predictor. This is the so called null model and is always use as a comparison for the fitted model.
Here the relevant part is the t-test for the coefficient of predictor height
in the output of the summary()
. This test is not significant with \(t(57) = 1.02\) and \(p = 0.312\). This means, the regression coefficient fo height
is not significantly different from 0.
mass
are kg.# create objekt
height_plot <- ggplot(sw_data, aes(x = height, y = mass))
# add a layer that is storede with the plot object
height_plot <- height_plot + geom_point()
# show plot
height_plot
## Warning: Removed 28 rows containing missing values (geom_point).
# add layer and store it directly using the same object name
height_plot <- height_plot + geom_smooth(method = "lm", se = F)
# show the stored plot object
height_plot
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 28 rows containing non-finite values (stat_smooth).
## Warning: Removed 28 rows containing missing values (geom_point).
# add layer and store it directly using the same object name
height_plot <- height_plot +
labs(title = "Hight and Mass in the Star Wars-Universe",
x = "Height in cm",
y = "Mass in kg")
# show plot
height_plot
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 28 rows containing non-finite values (stat_smooth).
## Warning: Removed 28 rows containing missing values (geom_point).
Hint: There might be more themes to be used. To our opinion theme_classic()
is the one that most fits the APA guidelines.
# add layer and store it directly using the same object name
height_plot <- height_plot + theme_classic()
# show plot
height_plot
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 28 rows containing non-finite values (stat_smooth).
## Warning: Removed 28 rows containing missing values (geom_point).
Take care: In the above parts the plot was overwritten at each step. Therefore we can store simply the plot object height_plot
.
ggsave("height_plot.png", height_plot)
Here again the whole syntax
# create plot object
height_plot <- ggplot(sw_data, aes(x = height, y = mass))
# add layers and overwrite object
height_plot <- height_plot +
geom_point() +
geom_smooth(method = "lm", se = F) +
labs(title = "Hight and Mass in the Star Wars-Universe",
x = "Heigth in cm",
y = "Mass in kg") +
theme_classic()
From the plot we suspect, that only one single outlier might have had too much influence on our results. We want to clarify that.
plot()
to the above generated regression model. Follow the hints on the console. There you should find “press enter for the next plot”. You will see four plots in total, one by one.plot(m_height)
Alternatively we can see all plots at once:
par(mfrow = c(2,2))
plot(m_height)
In all of the plots observation no 16 is special. All the other values look good.
We know, that observation 16 is problematic. We can check this observation using the slicing method (square brackets) to check what we have in this line.
Take care: Although we want to see a single line only we need to use the method [<lines>, <columns>]
. Therefore we need to put the comma. We may leave the value for columns empty. So the default shows us all columns that fit to the console.
sw_data[16,]
## # A tibble: 1 x 10
## name height mass hair_color skin_color eye_color birth_year gender homeworld species
## <chr> <dbl> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr> <chr>
## 1 Jabba Desili… 175 1358 <NA> green-tan, b… orange 600 hermaphr… Nal Hutta Hutt
Jabba seems to be responsable for the problems. Looking at his data we see, that this makes sense: With a height of 1.75 m his weight is 1.358 tons.
sw_data
named sw_data_ex
where you exclude the problematic observation.summary()
.We may use the command filter()
for this purpose. We would then need the exact name of the observation in question. We could choose the data using square brackets (slicing) via <tibble>[<rows>, <columns>]
sw_data[16,1]
## # A tibble: 1 x 1
## name
## <chr>
## 1 Jabba Desilijic Tiure
Now, that we know the full name, we could use it in the command filter()
. We use name != "Jabba Desilijic Tiure"
to get all the observations (rows) where the name is not equal Jabba Desilijic Tiure (this is, what !=
stands for).
sw_data_ex <- sw_data %>% filter(name != "Jabba Desilijic Tiure")
Fit model
m_height_ex <- lm(mass ~ height, data = sw_data_ex)
Show output
summary(m_height_ex)
##
## Call:
## lm(formula = mass ~ height, data = sw_data_ex)
##
## Residuals:
## Min 1Q Median 3Q Max
## -39.382 -8.212 0.211 3.846 57.327
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -32.54076 12.56053 -2.591 0.0122 *
## height 0.62136 0.07073 8.785 4.02e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 19.14 on 56 degrees of freedom
## (28 observations deleted due to missingness)
## Multiple R-squared: 0.5795, Adjusted R-squared: 0.572
## F-statistic: 77.18 on 1 and 56 DF, p-value: 4.018e-12
The only changes we need compared to the code above is … 1. … the name of the data object is changed 2. … the data in use (sw_data_ex
) 3. … the subtitle, that we didn’t use before. Here we indicate, that this plot excludes the data of Jabba.
# create object
height_plot_ex <- ggplot(sw_data_ex, aes(x = height, y = mass))
# add layers and overwrite object
height_plot <- height_plot +
geom_point() +
geom_smooth(method = "lm", se = F) +
labs(title = "Hight and Mass in the Star Wars-Universe",
subtitle = "Jabba excluded",
x = "Heigth in cm",
y = "Mass in kg") +
theme_classic()
Best if we view the two outputs in parallel:
summary(m_height) # Model with Jabba
##
## Call:
## lm(formula = mass ~ height, data = sw_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -61.43 -30.03 -21.13 -17.73 1260.06
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -13.8103 111.1545 -0.124 0.902
## height 0.6386 0.6261 1.020 0.312
##
## Residual standard error: 169.4 on 57 degrees of freedom
## (28 observations deleted due to missingness)
## Multiple R-squared: 0.01792, Adjusted R-squared: 0.0006956
## F-statistic: 1.04 on 1 and 57 DF, p-value: 0.312
summary(m_height_ex) # Model without Jabba
##
## Call:
## lm(formula = mass ~ height, data = sw_data_ex)
##
## Residuals:
## Min 1Q Median 3Q Max
## -39.382 -8.212 0.211 3.846 57.327
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -32.54076 12.56053 -2.591 0.0122 *
## height 0.62136 0.07073 8.785 4.02e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 19.14 on 56 degrees of freedom
## (28 observations deleted due to missingness)
## Multiple R-squared: 0.5795, Adjusted R-squared: 0.572
## F-statistic: 77.18 on 1 and 56 DF, p-value: 4.018e-12
Comparison | with Jabba | without Jabba |
---|---|---|
\(R^2\) | \(0.018\) | \(0.589\) |
F-Test | \(F(1,57) = 1.04\), \(p = 0.312\) | \(F(1, 56) = 77.18\), \(p < .001\) |
t-Test for \(\hat{\beta}_1\) | \(t(57)=1.02\), \(p = 0.312\) | \(t(56)=8.79\), \(p < .001\) |
It is important to distinguish between exploratory results and confirmatory ones. As we did not have hypotheses beforehead, we have exploratory results here. We can use them, to generate new hypotheses, that we can check afterwards in a new series of experiments. If we find then the predicted effects in such a confirmatory study, this is good evidence in favor of a hypothesis or theory.
It is obvious, that Jabba is a special case. For him there is no such a relation of height and weight as for the other observations in the dataset.
So we could derive the hypothesis, that species is also an important factor for the weight of an individual. This hypothesis could be checked confirmatively with newly collected data.
From the regression without Jabba, we can derive the hypothesis, that there is a close relation between weight and height for a lot of characters in the Star Wars Universe. So we could assume, that we could predict weight from height in such a population. Now we can collect new data to check this explorative hypothesis confirmatorily.
Annotation: This exercise sheet bases in part on exercises, that you can find in the textbook Dicovering Statistics Using R (Field, Miles & Field, 2012). They were modified for the purpose of this sheet and the R-code was actualized.
Field, A., Miles, J., & Field, Z. (2012). Discovering Statistics Using R. London: SAGE Publications Ltd.