Explorative Datenanalyse mit R The R Bootcamp |
adapted from trueloveproperty.co.uk
In diesem Practical wirst du das Transformieren, Gruppieren und Analysieren von Daten mit dplyr
üben.
Am Ende des Practicals wirst du wissen wie man:
Öffne dein TheRBootcamp
R project. Es sollte bereits die Ordner 1_Data
und 2_Code
enthalten.
Öffne ein neues R Skript. Schreibe deinen Namen, das Datum und “Wrangling II Practical” als Kommentare an den Anfang des Skripts.
## NAME
## DATUM
## Wrangling II Practical
Speichere das neue Skript unter dem Namen wrangling_II_practical.R
im 2_Code
Ordner.
Lade das tidyverse
.
# Pakete laden
library(tidyverse)
library(tidyverse)
In diesem Abschnitt arbeitest du zunächst mit dem bevoelkerung.csv
Datensatz. Er enthält die Einwohnerzahlen verschiedener Schweizer Städte von 1930 bis 2011. Im Datensätze
Tab findest du eine Auflistung und eine kurze Beschreibung der im Datensatz enthaltenen Variablen.
read_csv()
Funktion in R ein und speichere ihn unter dem Namen bevoelkerung
.bevoelkerung <- read_csv(file = "1_Data/bevoelkerung.csv")
print()
) und die Variablennamen (names()
) anschaust.names(bevoelkerung)
[1] "Stadtname" "st_wbev_2011" "st_wbev_2001"
[4] "proz_ver-2001–2011" "bevdichte" "st_wbev_1930"
[7] "st_wbev_1970" "st_wbev_1980" "st_wbev_1990"
[10] "st_wbev_2000"
bevoelkerung
# A tibble: 161 x 10
Stadtname st_wbev_2011 st_wbev_2001 `proz_ver-2001–… bevdichte st_wbev_1930
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Basel 164516 164665 -0.1 69 148063
2 Bern 125681 122211 2.8 24 111783
3 Genève 188234 175697 7.1 119 124121
4 Lausanne 129383 115272 12.2 31 75915
5 Winterth… 103075 89484 15.2 15 53925
6 Zürich 376990 340197 10.8 43 290937
7 Biel-Bie… 51635 48142 7.3 24 37726
8 Lugano 55151 50877 8.4 17 17672
9 Luzern 78093 73233 6.6 27 47066
10 St. Gall… 73505 69857 5.2 19 63947
# … with 151 more rows, and 4 more variables: st_wbev_1970 <dbl>,
# st_wbev_1980 <dbl>, st_wbev_1990 <dbl>, st_wbev_2000 <dbl>
pivot_longer()
um das Format zu wechseln. Verwende "st_wbev_2011"
und "st_wbev_2001"
für das cols
Argument und "jahr" für
das names_to
Argument und speichere das Resultat als neues Objekt bevoelkerung_long
ab.# Transofmation vom Wide ins Long Format
bevoelkerung_long <- bevoelkerung %>%
pivot_longer(cols = c("XX", "XX"), names_to = "XX")
# Transofmation vom Wide ins Long Format
bevoelkerung_long <- bevoelkerung %>%
pivot_longer(cols = c("st_wbev_2011", "st_wbev_2001"), names_to = "jahr")
Printe den neu erstellten Datensatz. Alles wie erwartet?
Nun bringe nicht nur die Jahre 2001 und 2011, sondern alle im Datensatz vorhandenen Jahre ins Long Format. Schaue dir zunächst nochmals die Namen der Spalten mit names()
an.
names(bevoelkerung)
[1] "Stadtname" "st_wbev_2011" "st_wbev_2001"
[4] "proz_ver-2001–2011" "bevdichte" "st_wbev_1930"
[7] "st_wbev_1970" "st_wbev_1980" "st_wbev_1990"
[10] "st_wbev_2000"
st_wbev_XXX
. Das bedeutet, dass du die sehr hilfreiche starts_with()
Funktion zur Variablenauswahl verwenden kannst. Benutze pivot_longer()
und starts_with()
um alle Jahr-Variablen zu transformieren.# Transofmation vom Wide ins Long Format
bevoelkerung_long <- bevoelkerung %>%
pivot_longer(cols = starts_with("XX"), names_to = "XX")
bevoelkerung_long <- bevoelkerung %>%
pivot_longer(cols = starts_with("st_"), names_to = "jahr")
Printe nochmals bevoelkerung_long
.
Die Einwohnerzahl ist im neuen Datensatz mi dem Standardwert value
benannt. Führe nun nochmal die pivot_longer
Funktion aus, verwende nun aber auch noch das values_to
Argument um die neue Spalte einwohner
zu nennen.
# Transofmation vom Wide ins Long Format
bevoelkerung_long <- bevoelkerung %>%
pivot_longer(cols = starts_with("XX"), names_to = "XX", values_to = "XX")
bevoelkerung_long <- bevoelkerung %>%
pivot_longer(cols = starts_with("st_"), names_to = "jahr", values_to = "einwohner")
Schaue dir das Resultat an. Alles in Ordnung?
Verwende nun das names_prefix
Argument um die Präfixe der Jahreszahlen automatisch zu entfernen. Der character
-String der für names_prefix
bereit gestellt wird, wird vom Beginn der Variablennamen entfernt.
bevoelkerung_long <- bevoelkerung %>%
pivot_longer(starts_with("st_"), names_to = "jahr",
values_to = "einwohner",
names_prefix = "st_wbev_")
bevoelkerung_long
im Long Format bekommen hättest und sie ins Wide Format umwandeln müsstest. Verwende die pivot_wider()
Funktion und den Argumenten names_from
und values_from
die Spalten jahr
und einwohner
zu. Speichere das Ergebnis als bevoelkerung_wide
ab.# Transofmation vom Long ins Wide Format
bevoelkerung_wide <- bevoelkerung_long %>%
pivot_wider(names_from = XX, values_from = XX)
bevoelkerung_wide <- bevoelkerung_long %>%
pivot_wider(names_from = jahr, values_from = einwohner)
Vergleiche bevoelkerung_wide
mit bevoelkerung
. War die Rücktransformation erfolgreich? Was fehlt?
Um die zuvor entfernten Präfixe wieder bei den Variablennamen hinzuzufügen, kannst du das names_prefix
argument in pivot_wider()
verwenden. Benutze names_prefix
um "st_wbev_"
als Präfix wieder hinzuzufügen.
bevoelkerung_wide <- bevoelkerung_long %>%
pivot_wider(names_from = jahr, values_from = einwohner,
names_prefix = "st_wbev_")
Für den Rest des Practicals arbeitst du mit dem kc_house.csv
Datensatz. Er enthält Verkaufspreise von Häusern in King County, Washington. Aufgelistet sind Häuser, welche zwischen Mai 2014 und Mai 2015 verkauft wurden. Nebst den Verkaufspreisen enthält der Datensatz Spezifikationen der Häuser, z.B. die Anzahl Zimmer eines Hauses.
read_csv()
Funktion in R ein und speichere ihn unter dem Namen kc_house
.kc_house <- read_csv(file = "1_Data/kc_house.csv")
summary()
und names()
um einen Eindruck über dessen Struktur zu erhalten.kc_house
# A tibble: 21,613 x 11
preis schlafzimmer badezimmer qf_wohnraum qf_parzelle stoecke ufer
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2.22e5 3 1 1180 5650 1 0
2 5.38e5 3 2.25 2570 7242 2 0
3 1.80e5 2 1 770 10000 1 0
4 6.04e5 4 3 1960 5000 1 0
5 5.10e5 3 2 1680 8080 1 0
6 1.23e6 4 4.5 5420 101930 1 0
7 2.58e5 3 2.25 1715 6819 2 0
8 2.92e5 3 1.5 1060 9711 1 0
9 2.30e5 3 1 1780 7470 1 0
10 3.23e5 3 2.5 1890 6560 2 0
# … with 21,603 more rows, and 4 more variables: qf_dachstock <dbl>,
# qf_keller <dbl>, baujahr <dbl>, postleitzahl <dbl>
summary(kc_house)
preis schlafzimmer badezimmer qf_wohnraum
Min. : 75000 Min. : 0.0 Min. :0.00 Min. : 290
1st Qu.: 321950 1st Qu.: 3.0 1st Qu.:1.75 1st Qu.: 1427
Median : 450000 Median : 3.0 Median :2.25 Median : 1910
Mean : 540088 Mean : 3.4 Mean :2.11 Mean : 2080
3rd Qu.: 645000 3rd Qu.: 4.0 3rd Qu.:2.50 3rd Qu.: 2550
Max. :7700000 Max. :33.0 Max. :8.00 Max. :13540
qf_parzelle stoecke ufer qf_dachstock qf_keller
Min. : 520 Min. :1.00 Min. :0.000 Min. : 290 Min. : 0
1st Qu.: 5040 1st Qu.:1.00 1st Qu.:0.000 1st Qu.:1190 1st Qu.: 0
Median : 7618 Median :1.50 Median :0.000 Median :1560 Median : 0
Mean : 15107 Mean :1.49 Mean :0.008 Mean :1788 Mean : 292
3rd Qu.: 10688 3rd Qu.:2.00 3rd Qu.:0.000 3rd Qu.:2210 3rd Qu.: 560
Max. :1651359 Max. :3.50 Max. :1.000 Max. :9410 Max. :4820
baujahr postleitzahl
Min. :1900 Min. :98001
1st Qu.:1951 1st Qu.:98033
Median :1975 Median :98065
Mean :1971 Mean :98078
3rd Qu.:1997 3rd Qu.:98118
Max. :2015 Max. :98199
qm_wohnraum
, qm_dachstock
und qm_keller
, welche die jeweilige Raumgrösse in Quadratmeter angeben. Ein Quadratfuss entspricht 0.093 Quadratmeter.kc_house <- kc_house %>%
mutate(XX = XX * 0.093,
XX = XX * 0.093,
XX = XX * 0.093)
kc_house <- kc_house %>%
mutate(qm_wohnraum = qf_wohnraum * 0.093,
qm_dachstock = qf_dachstock * 0.093,
qm_keller = qf_keller * 0.093)
mutate()
eine neue Spalte qm_total
, welche die Summe aus qm_wohnraum
, qm_dachstock
und qm_keller
darstellt.kc_house <- kc_house %>%
mutate(qm_total = qm_wohnraum + qm_dachstock + qm_keller)
villa
hinzu (mit mutate()
), welche den Wert “ja” annimmt, wenn qm_total
grösser als 750 ist und “nein”, wenn qm_total
kleiner oder gleich 750 ist.kc_house <- kc_house %>%
mutate(villa = case_when(
qm_total > 750 ~ "ja",
qm_total <= 750~ "nein"))
summarise
data$col
Notation, berechne den Mittelwert über alle Hauspreise.mean(kc_house$preis)
[1] 540088
summarise()
Funktion. Besteht ein Unterschied in den Resultaten dieser und der vorherigen Aufgabe?kc_house %>%
summarise(
XX = mean(XX)
)
kc_house %>%
summarise(
preis_mean = mean(preis)
)
# A tibble: 1 x 1
preis_mean
<dbl>
1 540088.
max()
Funktion.kc_house %>%
summarise(
preis_max = max(preis)
)
# A tibble: 1 x 1
preis_max
<dbl>
1 7700000
arrange()
und der desc()
Funktion den Datensatz nach preis
in absteigender Reihenfolge und printe das Resultat. Richtig sortiert?kc_house <- kc_house %>%
arrange(desc(preis))
kc_house
# A tibble: 21,613 x 16
preis schlafzimmer badezimmer qf_wohnraum qf_parzelle stoecke ufer
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 7.70e6 6 8 12050 27600 2.5 0
2 7.06e6 5 4.5 10040 37325 2 1
3 6.88e6 6 7.75 9890 31374 2 0
4 5.57e6 5 5.75 9200 35069 2 0
5 5.35e6 5 5 8000 23985 2 0
6 5.30e6 6 6 7390 24829 2 1
7 5.11e6 5 5.25 8010 45517 2 1
8 4.67e6 5 6.75 9640 13068 1 1
9 4.50e6 5 5.5 6640 40014 2 1
10 4.49e6 4 3 6430 27517 2 0
# … with 21,603 more rows, and 9 more variables: qf_dachstock <dbl>,
# qf_keller <dbl>, baujahr <dbl>, postleitzahl <dbl>, qm_wohnraum <dbl>,
# qm_dachstock <dbl>, qm_keller <dbl>, qm_total <dbl>, villa <chr>
kc_house %>%
summarise(million_prozent = mean(XX > XX))
kc_house %>%
summarise(million_prozent = mean(preis > 1000000))
# A tibble: 1 x 1
million_prozent
<dbl>
1 0.0678
stoecke
) und Badezimmer (badezimmer
) von Villen (villa
). Verwende erst filter()
um Villen auszuwählen und danach summarise()
.kc_house %>%
filter(villa == "ja") %>%
summarise(
stoecke_mean = mean(stoecke),
badezimmer_mean = mean(badezimmer)
)
# A tibble: 1 x 2
stoecke_mean badezimmer_mean
<dbl> <dbl>
1 1.92 3.68
group_by
und summarise
group_by()
und n()
um zu berechnen wie viele Villen und wie viele normale Häuser (nicht-Villen) im Datensatz vorhanden sind.kc_house %>%
group_by(XX) %>%
summarise(N = XX)
kc_house %>%
group_by(villa) %>%
summarise(N = n())
# A tibble: 2 x 2
villa N
<chr> <int>
1 ja 751
2 nein 20862
summarise()
, der den mittlere Verkaufspreis von Villen und normalen Häusern (nicht-Villen) berechnet?kc_house %>%
group_by(villa) %>%
summarise(N = n(),
preis_mean = mean(preis))
# A tibble: 2 x 3
villa N preis_mean
<chr> <int> <dbl>
1 ja 751 1541915.
2 nein 20862 504024.
group_by()
und summarise()
, um auch noch das Maximum zu bestimmen.kc_house %>%
group_by(villa) %>%
summarise(N = n(),
preis_min = min(preis),
preis_mean = mean(preis),
preis_max = max(preis))
# A tibble: 2 x 5
villa N preis_min preis_mean preis_max
<chr> <int> <dbl> <dbl> <dbl>
1 ja 751 404000 1541915. 7700000
2 nein 20862 75000 504024. 3100000
baujahr
und berechne dann die mittlere Wohnfläche (qm_wohnraum
).kc_house %>%
group_by(baujahr) %>%
summarise(N = n(),
wohnraum = mean(qm_wohnraum))
# A tibble: 116 x 3
baujahr N wohnraum
<dbl> <int> <dbl>
1 1900 87 161.
2 1901 29 164.
3 1902 27 179.
4 1903 46 140.
5 1904 45 149.
6 1905 74 183.
7 1906 92 168.
8 1907 65 177.
9 1908 86 158.
10 1909 94 177.
# … with 106 more rows
postleitzahl
) 98001, 98109, 98117 und 98199. Stelle ihm einen neuen Datensatz theodorus
zusammen, welcher nur die Häuser dieser Gegend enthält. Tipp: der %in%
Operator testet ob Elemente des Vektors auf der rechten Seite im Vektor auf der linken Seite enthalten sind.theodorus <- kc_house %>%
filter(XX %in% c(XX, XX, XX, XX))
theodorus <- kc_house %>%
filter(postleitzahl %in% c(98001, 98109, 98117, 98199))
theodorus %>%
group_by(postleitzahl, villa) %>%
summarise(preis_mean = mean(preis),
stoecke_min = min(stoecke),
stoecke_max = max(stoecke),
N = n())
# A tibble: 8 x 6
# Groups: postleitzahl [4]
postleitzahl villa preis_mean stoecke_min stoecke_max N
<dbl> <chr> <dbl> <dbl> <dbl> <int>
1 98001 ja 665667. 1 2 3
2 98001 nein 277589. 1 2.5 359
3 98109 ja 2508333. 2 2.5 3
4 98109 nein 833528. 1 3 106
5 98117 ja 898750 2 2.5 2
6 98117 nein 575626. 1 3 551
7 98199 ja 1762618. 1 3 12
8 98199 nein 753625. 1 3 305
ufer
)? Printe nur diese Zeile des Datensatzes.kc_house %>%
group_by(postleitzahl) %>%
summarise(ufer_p = mean(ufer)) %>%
arrange(desc(ufer_p)) %>%
slice(1)
# A tibble: 1 x 2
postleitzahl ufer_p
<dbl> <dbl>
1 98070 0.203
kc_house %>%
mutate(preis_zu_flaeche = preis / qm_wohnraum) %>%
arrange(desc(preis_zu_flaeche)) %>%
slice(1)
# A tibble: 1 x 17
preis schlafzimmer badezimmer qf_wohnraum qf_parzelle stoecke ufer
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 874950 2 1 1080 4000 1 0
# … with 10 more variables: qf_dachstock <dbl>, qf_keller <dbl>, baujahr <dbl>,
# postleitzahl <dbl>, qm_wohnraum <dbl>, qm_dachstock <dbl>, qm_keller <dbl>,
# qm_total <dbl>, villa <chr>, preis_zu_flaeche <dbl>
kc_house %>%
group_by(postleitzahl) %>%
summarise(preis_mean = mean(preis)) %>%
arrange(desc(preis_mean)) %>%
slice(1:10)
# A tibble: 10 x 2
postleitzahl preis_mean
<dbl> <dbl>
1 98039 2160607.
2 98004 1355927.
3 98040 1194230.
4 98112 1095499.
5 98102 901258.
6 98109 879624.
7 98105 862825.
8 98006 859685.
9 98119 849448.
10 98005 810165.
baujahr | N | preis_mean | preis_max | qm_wohnraum_mean |
---|---|---|---|---|
1990 | 320 | 563966 | 3640900 | 234 |
1991 | 224 | 630441 | 5300000 | 244 |
1992 | 198 | 548169 | 2480000 | 223 |
1993 | 202 | 556612 | 3120000 | 226 |
1994 | 249 | 486834 | 2880500 | 209 |
1995 | 169 | 577771 | 3200000 | 224 |
1996 | 195 | 639534 | 3100000 | 240 |
1997 | 177 | 606058 | 3800000 | 234 |
1998 | 239 | 594159 | 1960000 | 241 |
kc_house %>%
filter(baujahr >= 1990 & baujahr < 1999) %>%
group_by(baujahr) %>%
summarise(N = n(),
preis_mean = mean(preis),
preis_max = max(preis),
qm_wohnraum_mean = mean(qm_wohnraum)) %>%
knitr::kable(digits = 0)
baujahr | N | preis_mean | preis_max | qm_wohnraum_mean |
---|---|---|---|---|
1990 | 320 | 563966 | 3640900 | 234 |
1991 | 224 | 630441 | 5300000 | 244 |
1992 | 198 | 548169 | 2480000 | 223 |
1993 | 202 | 556612 | 3120000 | 226 |
1994 | 249 | 486834 | 2880500 | 209 |
1995 | 169 | 577771 | 3200000 | 224 |
1996 | 195 | 639534 | 3100000 | 240 |
1997 | 177 | 606058 | 3800000 | 234 |
1998 | 239 | 594159 | 1960000 | 241 |
# Wrangling II mit dplyr and tidyr ---------------------------
library(tidyverse) # Lade tidyverse für dplyr
# Lese den basel Datensatz ein
basel <- read_csv("1_Data/basel.txt")
# Keine Gruppierungsvariable
bas <- basel %>%
summarise(
alter_m = mean(alter, na.rm = TRUE),
einkommen_median = median(einkommen, na.rm = TRUE),
N = n()
)
bas
# Eine Gruppierungsvariable
bas_ges <- basel %>%
group_by(geschlecht) %>%
summarise(
alter_m = mean(alter, na.rm = TRUE),
einkommen_median = median(einkommen, na.rm = TRUE),
N = n()
)
bas_ges
# Zwei Gruppierungsvariablen
bas_ges_bil <- basel %>%
group_by(geschlecht, bildung) %>%
summarise(
alter_m = mean(alter, na.rm = TRUE),
einkommen_median = median(einkommen, na.rm = TRUE),
N = n()
)
bas_ges_bil
# Gruppiere nach Geschlecht und Bildung und berechne den Mittelwert aller
# Variablen des Typs numeric
basel %>%
group_by(geschlecht, bildung) %>%
summarise_if(is.numeric, mean, na.rm = TRUE)
File | Zeilen | Spalten | Beschreibung |
---|---|---|---|
kc_house.csv | 21613 | 11 | Verkaufspreise von Häusern in King County zwischen Mai 2014 und Mai 2015. |
bevoelkerung.csv | 161 | 10 | Einwohnerzahlen Schweizer Städte von 1930 bis 2011. |
Erste 5 Zeilen und 5 Spalten von kc_house.csv
preis | schlafzimmer | badezimmer | qf_wohnraum | qf_parzelle |
---|---|---|---|---|
7700000 | 6 | 8.00 | 12050 | 27600 |
7062500 | 5 | 4.50 | 10040 | 37325 |
6885000 | 6 | 7.75 | 9890 | 31374 |
5570000 | 5 | 5.75 | 9200 | 35069 |
5350000 | 5 | 5.00 | 8000 | 23985 |
Variable | Beschreibung |
---|---|
preis | Preis in USD |
schlafzimmer | Anzahl Schlafzimmer |
badezimmer | Anzahl Badezimmer |
qf_wohnraum | Wohnraumfläche in Quadratfuss |
qf_parzelle | Parzellengrösse in Quadratfuss |
stoecke | Anzahl Stöcke |
ufer | Ist das Haus am Ufer gebaut (1) oder nicht (0) |
qf_dachstock | Dachstockfläche in Quadratfuss |
qf_keller | Kellerfläche in Quadratfuss |
baujahr | Baujahr |
postleitzahl | Postleitzahl |
Erste 5 Zeilen und 5 Spalten von bevoelkerung.csv
Stadtname | st_wbev_2011 | st_wbev_2001 | proz_ver-2001–2011 | bevdichte |
---|---|---|---|---|
Basel | 164516 | 164665 | -0.1 | 69 |
Bern | 125681 | 122211 | 2.8 | 24 |
Genève | 188234 | 175697 | 7.1 | 119 |
Lausanne | 129383 | 115272 | 12.2 | 31 |
Winterthur | 103075 | 89484 | 15.2 | 15 |
Variable | Beschreibung |
---|---|
Stadtname | Name der Stadt |
st_wbev_2011 | Wohnbevölkerung im Jahr 2011 |
st_wbev_2001 | Wohnbevölkerung im Jahr 2001 |
proz_ver-2001–2011 | Veränderung der Einwohnerzahl in Prozent zwischen 2001 und 2011 |
bevdichte | Bevölkerungsdichte |
st_wbev_1930 | Wohnbevölkerung im Jahr 1930 |
st_wbev_1970 | Wohnbevölkerung im Jahr 1970 |
st_wbev_1980 | Wohnbevölkerung im Jahr 1980 |
st_wbev_1990 | Wohnbevölkerung im Jahr 1990 |
st_wbev_2000 | Wohnbevölkerung im Jahr 2000 |
Paket | Installation | Beschreibung |
---|---|---|
tidyverse |
install.packages("tidyverse") |
Ein Metapaket für Data Science, einschliesslich dplyr , ggplot2 und weitere Pakete |
Wrangling
Funktion | Paket | Beschreibung |
---|---|---|
rename() |
dplyr |
Umbenennen von Spalten |
select() |
dplyr |
Auswahl von Spalten basierend auf Name oder Index |
filter() |
dplyr |
Auswahl von Zeilen basieren auf einem logischen Ausdruck |
arrange() |
dplyr |
Sortiere Zeilen |
mutate() |
dplyr |
Hinzufügen von Spalten |
case_when() |
dplyr |
Recodieren von Spalten |
group_by(), summarise() |
dplyr |
Gruppierung von Daten zur Berechnung deskriptiver Statistiken |
pivot_longer() |
tidyr |
Transormation vom Wide ins Long Format |
pivot_wider() |
tidyr |
Transormation vom Long ins Wide Format |