R Basis

Vom ersten Befehl bis zum ersten echten Datensatz

Willkommen

Heute lernen Sie die Grundlagen von R, Schritt für Schritt und immer mit eigenen Händen. Am Ende des Kurses öffnen Sie einen echten Datensatz mit über 90.000 Zeilen und beantworten erste Fragen dazu.

Erst lernen, dann anwenden. Jeder Abschnitt erklärt zuerst neue Befehle an Beispielen. Danach folgen Aufgaben, die genau diese Befehle abfragen.

Tippen statt kopieren. Die Beispiele lassen sich nicht kopieren. Wer selbst tippt, macht Fehler, und aus Fehlern lernt man am meisten.

Fehler sind eingeplant. In Finde den Fehler läuft der Code absichtlich schief. Ihre Aufgabe: Meldung lesen, reparieren.

Die Übungsfelder auf dieser Seite führen echtes R im Browser aus. Mit Ausführen sehen Sie sofort, ob Ihr Ergebnis stimmt. Sie können jede Aufgabe genauso in RStudio lösen.

RStudio

Die vier Fenster

Neu: Skript · Console · Strg + Enter · Kommentare mit #

Skript · oben links

Hier schreiben und speichern Sie Ihren Code.

Environment · oben rechts

Alles, was Sie angelegt haben.

Console · unten links

Hier läuft der Code, hier steht das Ergebnis.

Files / Plots / Help · unten rechts

Dateien, Grafiken, Hilfe.

Ein neues Skript öffnen Sie mit File → New File → R Script (oder Strg + Shift + N, Mac Cmd + Shift + N). Eine Zeile im Skript führen Sie aus, indem Sie den Cursor in die Zeile setzen und Strg + Enter drücken (Mac Cmd + Enter). Das Ergebnis erscheint in der Console.

Alles hinter einem # ist ein Kommentar. R ignoriert ihn. Kommentare sind Notizen für Sie selbst:

# Mein erstes Skript
1 + 1   # Kommentare gehen auch hinter Code
#> [1] 2

Die Zeile #> [1] 2 darunter ist die Ausgabe von R. Die [1] bedeutet: Das ist der erste Wert des Ergebnisses.

Aktion Windows Mac
Zeile ausführen Strg + Enter Cmd + Enter
Skript speichern Strg + S Cmd + S
Laufenden Befehl abbrechen Esc Esc

Ihr Zug in RStudio: Legen Sie ein neues Skript an, speichern Sie es als kurs_basis.R und tippen Sie die zwei Zeilen von oben ab. Führen Sie sie mit Strg + Enter aus. In der Console sollte [1] 2 erscheinen.

Sie tippen Code direkt in die Console statt ins Skript. Was passiert beim Schließen von RStudio?

  • Der Code wird automatisch im Skript gespeichert
  • Der Code ist weg, nur das Skript bleibt erhalten
  • RStudio fragt, in welche Datei der Code soll

Die Console rechnet, merkt sich aber nichts dauerhaft. Darum gehört jeder Code, den Sie behalten wollen, ins Skript.

R als Taschenrechner

Grundrechenarten

Neu: + - * / ^ · Klammern · Dezimalpunkt

R rechnet wie ein Taschenrechner. Tippen Sie jede Zeile in Ihr Skript und führen Sie sie aus:

5 + 3     # Addition
#> [1] 8
10 - 4    # Subtraktion
#> [1] 6
6 * 7     # Multiplikation: Stern
#> [1] 42
20 / 8    # Division: Schrägstrich
#> [1] 2.5
2^3       # Potenz: 2 hoch 3 = 2 * 2 * 2
#> [1] 8

R hält sich an Punkt vor Strich. Was zuerst gerechnet werden soll, setzen Sie in runde Klammern:

2 + 3 * 4     # erst 3 * 4, dann + 2
#> [1] 14
(2 + 3) * 4   # erst die Klammer
#> [1] 20

Dezimalzahlen schreibt R mit Punkt, nicht mit Komma: 3.5 statt 3,5.

3.5 * 2
#> [1] 7

Aufgabe 1

Berechnen Sie: Die Summe aus 12 und 8, multipliziert mit 3, geteilt durch 4.

Die Summe muss zuerst gerechnet werden. Setzen Sie sie in Klammern: (12 + 8).

Aufgabe 2

Berechnen Sie 2 hoch 8 und ziehen Sie davon 56 ab.

„Hoch“ schreibt R mit ^.

Finde den Fehler 1

Eine Wohnung hat 3,5 Zimmer, jedes kostet 450 € Miete. Klicken Sie zuerst auf Ausführen, lesen Sie die Meldung und reparieren Sie dann den Code.

Die Meldung nennt unexpected ','. Wie schreibt R Dezimalzahlen?

Funktionen

Neu: sqrt() · pi · round() · ceiling() · floor()

Für alles, was über die Grundrechenarten hinausgeht, hat R Funktionen. Eine Funktion hat einen Namen, danach folgen runde Klammern. In die Klammern schreiben Sie den Wert, mit dem die Funktion arbeiten soll:

sqrt(16)   # Wurzel (englisch: square root)
#> [1] 4
sqrt(2)
#> [1] 1.414214

Manche Zahlen kennt R schon. Die Kreiszahl π heißt in R pi, ganz ohne Klammern:

pi
#> [1] 3.141593

Manche Funktionen brauchen mehr als einen Wert. Diese Argumente trennen Sie mit Komma. round() rundet eine Zahl auf so viele Nachkommastellen, wie Sie als zweites Argument angeben:

round(pi, 2)     # pi auf 2 Nachkommastellen
#> [1] 3.14
round(7.567, 1)  # auf 1 Nachkommastelle
#> [1] 7.6
round(7.567)     # ohne zweites Argument: auf eine ganze Zahl
#> [1] 8

Immer auf- oder immer abrunden auf eine ganze Zahl:

ceiling(4.1)   # aufrunden
#> [1] 5
floor(4.9)     # abrunden
#> [1] 4

Funktionen lassen sich ineinander schachteln und mit Rechenzeichen verbinden. R rechnet dann von innen nach außen:

sqrt(9) + 1          # 3 + 1
#> [1] 4
round(sqrt(2), 3)    # erst die Wurzel, dann runden
#> [1] 1.414

Zu jeder Funktion gibt es eine Hilfeseite. Tippen Sie in die Console ein Fragezeichen vor den Namen, zum Beispiel ?round.

Aufgabe 3

Berechnen Sie die Summe aus der Wurzel von 16 und π. Runden Sie das Ergebnis auf 2 Nachkommastellen.

Die Wurzel von 16 ist sqrt(16), π ist pi. Beides addieren Sie mit +.

Aufgabe 4

Die Fläche eines Kreises ist π mal Radius hoch 2. Berechnen Sie die Fläche eines Kreises mit Radius 3 und runden Sie auf eine Nachkommastelle.

Radius hoch 2 schreiben Sie als 3^2. Die Fläche ist pi * 3^2.

Objekte

Neu: Zuweisung mit <- · Namen · Groß- und Kleinschreibung

Ergebnisse können Sie unter einem Namen speichern. Dafür gibt es den Pfeil <-, gebildet aus < und -. Lesen Sie ihn als „bekommt“:

preis <- 4.99      # preis bekommt den Wert 4.99
anzahl <- 3

R gibt dabei nichts aus. Die Werte stehen jetzt aber oben rechts im Environment. Mit dem Namen rechnen Sie weiter, als stünde dort die Zahl:

gesamt <- preis * anzahl
gesamt              # Name allein ausführen = Inhalt anzeigen
#> [1] 14.97
round(gesamt, 1)
#> [1] 15

Regeln für Namen: Sie beginnen mit einem Buchstaben und enthalten keine Leerzeichen (statt Leerzeichen einen Unterstrich: preis_pro_stueck). R unterscheidet Groß- und Kleinschreibung: Preis und preis sind zwei verschiedene Namen.

Tastenkürzel für den Pfeil: Alt + - (Mac Option + -).

Aufgabe 5 · Pizza-Abend

Vier Freunde bestellen drei Pizzen zu je 8,90 €. Dazu kommen 10 % Trinkgeld; der Betrag wird also mit 1.1 multipliziert.

  1. Speichern Sie den Pizzapreis im Objekt pizza.
  2. Berechnen Sie den Gesamtbetrag mit Trinkgeld und speichern Sie ihn in gesamt.
  3. Wie viel zahlt jede Person? Runden Sie auf 2 Nachkommastellen.

gesamt <- 3 * pizza * 1.1

Pro Person heißt: gesamt / 4. Das Ganze kommt in round(…, 2).

Finde den Fehler 2

Dieser Code soll den Gesamtpreis berechnen. R findet ein Objekt nicht. Welches, und warum?

Vergleichen Sie Preis in Zeile 1 mit preis in Zeile 3.

Fehlermeldungen lesen

Sie haben jetzt zwei typische Fehler gesehen. Hier die häufigsten Meldungen im Überblick:

Meldung Was R Ihnen sagen will Häufige Ursache
object 'x' not found Den Namen kenne ich nicht. Tippfehler, Groß/klein, Objekt noch nicht angelegt
could not find function "x" Diese Funktion kenne ich nicht. Tippfehler im Funktionsnamen
unexpected symbol / unexpected ',' Der Satzbau stimmt nicht. Komma, Klammer oder Rechenzeichen fehlt oder ist zu viel
non-numeric argument to binary operator Mit Text kann ich nicht rechnen. Zahl steht in Anführungszeichen
+ am Anfang der Console Ich warte, der Befehl ist nicht fertig. Klammer nicht geschlossen. Mit Esc abbrechen.
TippSo gehen Sie bei einem Fehler vor
  1. Meldung lesen und das genannte Objekt oder Zeichen suchen.
  2. Die Zeile Zeichen für Zeichen mit dem Beispiel vergleichen.
  3. Erst dann fragen, gern mit der Fehlermeldung.

Vektoren

Mehrere Werte auf einmal

Neu: c() · sum() · mean() · length() · max() · min()

Bisher stand in jedem Objekt ein Wert. Mit c() (für combine, verbinden) fassen Sie mehrere Werte zu einem Vektor zusammen. Ein Schrittzähler hat eine Woche lang mitgezählt, von Montag bis Sonntag:

schritte <- c(8200, 4300, 12100, 8000, 10400, 15800, 3100)
schritte
#> [1]  8200  4300 12100  8000 10400 15800  3100

Rechnen Sie mit einem Vektor, rechnet R mit jedem Wert einzeln:

schritte / 1000   # jeder Wert durch 1000
#> [1]  8.2  4.3 12.1  8.0 10.4 15.8  3.1

Diese Funktionen fassen einen Vektor zu einer Zahl zusammen:

sum(schritte)      # Summe aller Werte
#> [1] 61900
mean(schritte)     # Mittelwert (Durchschnitt)
#> [1] 8842.857
length(schritte)   # Anzahl der Werte
#> [1] 7
max(schritte)      # größter Wert
#> [1] 15800
min(schritte)      # kleinster Wert
#> [1] 3100

Aufgabe 6

Sie haben diese Woche in der Mensa fünfmal gegessen und dafür 4,50 €, 3,90 €, 5,20 €, 4,50 € und 6,10 € bezahlt. Legen Sie den Vektor mensa an und berechnen Sie, wie viel Sie insgesamt ausgegeben haben.

Die Werte trennen Sie in c() mit Komma, Dezimalzahlen schreiben Sie mit Punkt: c(4.5, 3.9, …).

Aufgabe 7

Wie viel hat ein Mensaessen im Durchschnitt gekostet? Runden Sie auf 2 Nachkommastellen.

Den Durchschnitt berechnet mean().

Werte auswählen

Neu: eckige Klammern [ ] · Folgen mit : · seq()

Mit eckigen Klammern holen Sie einzelne Werte aus einem Vektor. In die Klammer schreiben Sie die Position. R beginnt bei 1 zu zählen:

schritte[1]         # erster Wert (Montag)
#> [1] 8200
schritte[7]         # siebter Wert (Sonntag)
#> [1] 3100

Mehrere Positionen geben Sie mit c() an. Eine lückenlose Folge schreiben Sie kürzer mit Doppelpunkt: 2:4 bedeutet 2, 3, 4.

schritte[c(1, 3)]   # Montag und Mittwoch
#> [1]  8200 12100
2:4
#> [1] 2 3 4
schritte[2:4]       # Dienstag bis Donnerstag
#> [1]  4300 12100  8000

Folgen mit anderen Abständen erzeugt die Funktion seq(). Sie bekommt drei Argumente: Startwert (from), Endwert (to) und Schrittweite (by):

seq(from = 0, to = 100, by = 25)
#> [1]   0  25  50  75 100
seq(from = 1, to = 9, by = 2)
#> [1] 1 3 5 7 9

Hier sehen Sie, dass man Argumente auch mit Namen angeben kann: from = 0. Das macht Code leichter lesbar.

Was liefert schritte[8]? Die Woche hat nur sieben Tage.

NA, das steht für not available: Diesen Wert gibt es nicht. R meldet keinen Fehler, sondern sagt „hier ist nichts“. NA begegnet Ihnen in echten Daten oft, zum Beispiel bei fehlenden Antworten in Umfragen.

Aufgabe 8

Wie viele Schritte waren es im Schnitt am Wochenende, also an Tag 6 und 7?

Positionen 6 bis 7 schreiben Sie als 6:7.

Aufgabe 9

  1. Erzeugen Sie mit seq() die Zahlen von 12 bis 24 in 2er-Schritten und speichern Sie sie in x.
  2. Teilen Sie die Summe von x durch π und runden Sie das Ergebnis auf eine ganze Zahl auf.

Die Summe bekommen Sie mit sum(x), π mit pi.

Aufrunden auf eine ganze Zahl: ceiling(sum(x) / pi)

Datentypen

Neu: Zahlen · Text in "…" · TRUE/FALSE · class()

Vektoren können nicht nur Zahlen enthalten. Die drei wichtigsten Typen:

zahlen <- c(1.5, 2, 3)             # Zahlen (numeric)
staedte <- c("Berlin", "Hamburg")  # Text (character): immer in Anführungszeichen
erledigt <- c(TRUE, FALSE, TRUE)   # Wahrheitswerte (logical): TRUE oder FALSE

Welchen Typ ein Objekt hat, verrät class():

class(zahlen)
#> [1] "numeric"
class(staedte)
#> [1] "character"
class(erledigt)
#> [1] "logical"

Ein Vektor hat immer nur einen Typ. Mischen Sie Typen, macht R alles zu Text. Mit Text kann R nicht rechnen:

gemischt <- c(1, "zwei", 3)
gemischt
#> [1] "1"    "zwei" "3"
class(gemischt)
#> [1] "character"

Welchen Typ hat c("1", "2", "3")?

  • numeric, es sind ja Zahlen
  • character, wegen der Anführungszeichen
  • logical

Alles in Anführungszeichen ist für R Text, auch Ziffern. "1" ist ein Zeichen, 1 ist eine Zahl.

Finde den Fehler 3

Jemand hat Klausurnoten eingetippt und möchte den Durchschnitt. R gibt eine Warnung und NA aus. Prüfen Sie den Typ von noten und reparieren Sie den Code.

Probieren Sie class(noten). Was macht die Anführungszeichen aus den Zahlen?

Logik und Filtern

Vergleichen und zählen

Neu: == != > < >= <= · TRUE zählt als 1

Ein Vergleich beantwortet eine Ja/Nein-Frage. Bei einem Vektor beantwortet R sie für jeden Wert einzeln:

schritte >= 10000   # An welchen Tagen mindestens 10.000 Schritte?
#> [1] FALSE FALSE  TRUE FALSE  TRUE  TRUE FALSE
Zeichen Bedeutung Zeichen Bedeutung
== gleich (zwei Gleichheitszeichen!) != ungleich
> größer >= größer oder gleich
< kleiner <= kleiner oder gleich

Jetzt der wichtigste Trick des Tages: Für R ist TRUE gleich 1 und FALSE gleich 0. Deshalb gilt:

  • sum() eines Vergleichs zählt, wie oft er zutrifft.
  • mean() eines Vergleichs ist der Anteil, wie oft er zutrifft.
sum(schritte >= 10000)    # an wie vielen Tagen?
#> [1] 3
mean(schritte >= 10000)   # an welchem Anteil der Tage?
#> [1] 0.4285714

Aufgabe 10

An wie vielen Tagen lag die Schrittzahl unter 5000?

„Unter 5000“ heißt schritte < 5000.

Aufgabe 11

An welchem Anteil der Tage wurden mindestens 8000 Schritte erreicht? Runden Sie auf 2 Nachkommastellen.

Den Anteil liefert mean() eines Vergleichs. „Mindestens“ heißt >=.

Filtern

Neu: Bedingung in [ ] · & (und) · | (oder)

Bisher standen in den eckigen Klammern Positionen. Sie können dort auch einen Vergleich hineinschreiben. Dann behält R nur die Werte, bei denen TRUE herauskommt. Das nennt man Filtern:

schritte[schritte >= 10000]          # nur die Tage ab 10.000
#> [1] 12100 10400 15800
mean(schritte[schritte >= 10000])    # deren Durchschnitt
#> [1] 12766.67

Zwei Bedingungen verbinden Sie mit & (beide müssen zutreffen) oder | (mindestens eine muss zutreffen):

schritte[schritte > 5000 & schritte < 9000]    # zwischen 5000 und 9000
#> [1] 8200 8000
schritte[schritte < 4000 | schritte > 15000]   # sehr wenig oder sehr viel
#> [1] 15800  3100

Aufgabe 12

Wie viele Schritte waren es im Durchschnitt an den Tagen unter 8000?

Erst filtern, dann den Mittelwert bilden: schritte[schritte < 8000].

Aufgabe 13 · Bonus

Zeigen Sie alle Schrittzahlen, die mindestens 8000 und höchstens 12000 betragen.

Zwei Bedingungen, die beide zutreffen müssen: schritte >= 8000 & schritte <= 12000.

Finde den Fehler 4

Gesucht sind alle Tage mit mindestens 10.000 Schritten.

Schauen Sie in die Tabelle der Vergleichszeichen: Wie schreibt man „größer oder gleich“?

Tabellen

Eine Tabelle anlegen

Neu: data.frame() · $ · nrow() · ncol()

Eine Tabelle heißt in R Data Frame. Sie ist wie ein Tabellenblatt in Excel: Jede Spalte ist ein Vektor, alle Spalten sind gleich lang. Sie bauen sie mit data.frame() aus benannten Vektoren:

lerngruppe <- data.frame(
  name    = c("Ali", "Bea", "Chris", "Dana", "Emil", "Fiona"),
  fach    = c("BWL", "Psychologie", "BWL", "Informatik", "Psychologie", "BWL"),
  stunden = c(12, 20, 8, 15, 25, 10),
  note    = c(2.3, 1.7, 3.0, 2.0, 1.3, 2.7)
)
lerngruppe
#>    name        fach stunden note
#> 1   Ali         BWL      12  2.3
#> 2   Bea Psychologie      20  1.7
#> 3 Chris         BWL       8  3.0
#> 4  Dana  Informatik      15  2.0
#> 5  Emil Psychologie      25  1.3
#> 6 Fiona         BWL      10  2.7

Wie groß ist die Tabelle?

nrow(lerngruppe)   # Anzahl Zeilen
#> [1] 6
ncol(lerngruppe)   # Anzahl Spalten
#> [1] 4

Mit dem Dollarzeichen $ holen Sie eine Spalte heraus. Heraus kommt ein ganz normaler Vektor, mit dem Sie alles machen können, was Sie über Vektoren gelernt haben:

lerngruppe$stunden
#> [1] 12 20  8 15 25 10
sum(lerngruppe$stunden)
#> [1] 90

Aufgabe 14

Wie ist die Durchschnittsnote der Lerngruppe? Runden Sie auf 2 Nachkommastellen.

Die Spalte holen Sie mit lerngruppe$note.

Zeilen und Spalten auswählen

Neu: [Zeile, Spalte] · Zeilen filtern

Bei Vektoren stand in der eckigen Klammer eine Angabe. Bei Tabellen sind es zwei, getrennt durch ein Komma: erst die Zeilen, dann die Spalten. Bleibt eine Stelle leer, heißt das „alle“:

lerngruppe[2, ]                    # Zeile 2, alle Spalten
#>   name        fach stunden note
#> 2  Bea Psychologie      20  1.7
lerngruppe[, "note"]               # alle Zeilen, Spalte note
#> [1] 2.3 1.7 3.0 2.0 1.3 2.7
lerngruppe[2, "note"]              # Zeile 2, Spalte note
#> [1] 1.7

Wie beim Vektor können Sie vor dem Komma einen Vergleich verwenden. So filtern Sie Zeilen:

lerngruppe[lerngruppe$fach == "BWL", ]          # alle Zeilen mit BWL
#>    name fach stunden note
#> 1   Ali  BWL      12  2.3
#> 3 Chris  BWL       8  3.0
#> 6 Fiona  BWL      10  2.7
lerngruppe[lerngruppe$stunden > 12, "name"]     # Namen aller, die mehr als 12 Stunden lernten
#> [1] "Bea"  "Dana" "Emil"

Auch eine einzelne Spalte lässt sich filtern, denn sie ist ja ein Vektor:

lerngruppe$note[lerngruppe$fach == "BWL"]       # Noten der BWL-Studierenden
#> [1] 2.3 3.0 2.7

Aufgabe 15

Wie viele Stunden haben die BWL-Studierenden im Durchschnitt gelernt?

Die Bedingung lautet lerngruppe$fach == "BWL", genau wie im letzten Beispiel.

Aufgabe 16

Welche Personen haben eine Note besser als 2,0, also kleiner als 2.0? Geben Sie nur die Namen aus.

Vor das Komma kommt die Bedingung lerngruppe$note < 2.0, hinter das Komma der Spaltenname "name".

Finde den Fehler 5

Gesucht sind alle Zeilen der Psychologie-Studierenden. R meldet undefined columns selected.

Bei Tabellen braucht die eckige Klammer zwei Angaben: [Zeile, Spalte]. Was fehlt?

Neue Spalten

Neu: Spalte anlegen oder überschreiben mit tabelle$spalte <- …

Eine neue Spalte entsteht, indem Sie ihr mit <- Werte zuweisen. Gibt es die Spalte schon, wird sie überschrieben:

lerngruppe$minuten <- lerngruppe$stunden * 60    # neue Spalte
lerngruppe$sehr_gut <- lerngruppe$note < 2.0     # neue Spalte mit TRUE/FALSE
lerngruppe
#>    name        fach stunden note minuten sehr_gut
#> 1   Ali         BWL      12  2.3     720    FALSE
#> 2   Bea Psychologie      20  1.7    1200     TRUE
#> 3 Chris         BWL       8  3.0     480    FALSE
#> 4  Dana  Informatik      15  2.0     900    FALSE
#> 5  Emil Psychologie      25  1.3    1500     TRUE
#> 6 Fiona         BWL      10  2.7     600    FALSE

Aufgabe 17 · BMI

In der Tabelle personen stehen Größe (in cm) und Gewicht (in kg) von neun Personen.

  1. Rechnen Sie die Größe in Meter um, indem Sie die Spalte groesse überschreiben (durch 100 teilen).
  2. Legen Sie die Spalte bmi an, gerundet auf eine Nachkommastelle. Der BMI ist Gewicht geteilt durch Größe in Metern hoch 2.
  3. Zählen Sie, wie viele Personen einen BMI von 25 oder mehr haben.

Umrechnen: personen$groesse / 100. Der BMI: personen$gewicht / personen$groesse^2.

Zählen wie bei den Schritten: sum(personen$bmi >= 25)

Abschluss

Was liefert mean(c(TRUE, FALSE, TRUE, TRUE))?

  • Einen Fehler, weil man aus TRUE/FALSE keinen Mittelwert bilden kann
  • 0.75
  • 3

TRUE zählt als 1, FALSE als 0. Der Mittelwert ist also der Anteil der TRUE, genau so haben Sie die Rückkehrquoten berechnet.

Was ist der Unterschied zwischen <- und ==?

  • <- speichert einen Wert, == vergleicht zwei Werte
  • Es gibt keinen, beide speichern
  • == speichert, <- vergleicht

preis <- 5 legt ein Objekt an. preis == 5 fragt nur: Ist preis gleich 5? Die Antwort ist TRUE oder FALSE.

Spickzettel

+ - * / ^

Rechnen

sqrt(), pi, round(x, 2)

Funktionen

x <- 5

Wert speichern

c(1, 2, 3)

Vektor bauen

sum(), mean(), max()

Zusammenfassen

x[2], x[2:4]

Werte auswählen

x[x > 3]

Filtern

sum(x > 3), mean(x > 3)

Zählen, Anteil

df$spalte

Spalte holen

df[bedingung, ]

Zeilen filtern

read.csv("datei.csv")

Daten einlesen

head(), str(), table()

Überblick verschaffen

Zwischenstand: Mit dem Tor bei Level 30 kommen nach 7 Tagen 19,0 % zurück, bei Level 40 nur 18,2 %. Ist das ein echter Unterschied oder Zufall? Das klären wir im Fortgeschrittenenkurs, mit dem tidyverse, Grafiken und einem statistischen Test.