-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatenanalyse.qmd
More file actions
3348 lines (2551 loc) · 117 KB
/
Copy pathdatenanalyse.qmd
File metadata and controls
3348 lines (2551 loc) · 117 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: "Datenanalyse in 6 Schritten"
subtitle: "Eine Anleitung in der statistischen Programmiersprache R"
author: "Patrik Häcki"
date: "today"
date-format: "long"
abstract-title: "Version"
abstract: "5.7"
format:
html:
toc: true
toc-depth: 4
toc-title: Inhalt
other-links:
- text: Datenpfad
href: https://www.datenpfad.ch/
target: _blank
icon: house-door
html-math-method: katex
anchor-sections: true
smooth-scroll: true
link-external-icon: false
link-external-newwindow: true
comments: false
code-fold: show
code-summary: "Code anzeigen"
# code-tools:
# source: false
# toggle: true
# caption: "Code"
code-block-bg: false
code-block-border-left: "#9FC131"
highlight-style: atom-one
code-copy: true
brand: true
# theme:
# - zephyr
# - brand
lightbox: true
editor: source
lang: de
---
# Einführung
## Was ist R?
R ist eine kostenlose Open Source-Software für statistische Datenverarbeitung, die über die Website <https://stat.ethz.ch/CRAN> bezogen werden kann. Dabei umfasst R zum einen eine Vielzahl an Möglichkeiten zur Verarbeitung und Auswertung von Daten, die sich ohne grossen Aufwand nutzen lassen. Zum anderen kann man statistische Verfahren auch selbst programmieren und R fast beliebig erweitern. Von Anwendern erstellte Erweiterungen werden als Pakete oder packages bezeichnet und von ihren Programmierern oftmals für alle zugänglich gemacht. Im Comprehensive R Archive Network (kurz: CRAN), einem Netz aus Webservern, die Pakete und Code für R bereitstellen, sind eine Vielzahl solcher Pakete gelistet. Daneben wird auch Base R durch ein Kern-Team von Entwicklern ständig weiterentwickelt. R ist open-source, d.h. der Source Code ist unter der GNU Public License frei verfügbar.
## Vorteile von R
Die wesentlichen Vorteile von R lassen sich insgesamt wie folgt zusammenfassen:
- R kann kostenlos heruntergeladen und installiert werden.
- R steht für Windows-, Unix- und Mac-Systeme zur Verfügung.
- R wird von einem Kern-Team von Entwicklern ständig weiterentwickelt.
- Es gibt eine Vielzahl von frei zugänglichen Erweiterungen, die von der kontinuierlich wachsenden R-Community erstellt werden.
- R kann durch den Nutzer selbst erweitert werden.
Aufgrund dieser Vorteile findet R zunehmend Verbreitung und wird nicht nur im wissenschaftlichen Bereich, sondern auch für Anwendungen in der Wirtschaft eingesetzt.
## Installation
### R
Zentrale Anlaufstelle für den Download von R, für Zusatzpakete sowie für frei verfügbare Literatur ist die R-Projektseite <https://www.r-project.org> (in Englisch) oder das Comprehensive R Archive Network für die Schweiz [https://stat.ethz.ch/CRAN](https://stat.ethz.ch/CRAN/){.uri}, welches von der ETH Zürich betreut wird.
### R-Editor
Anders als manche seiner kommerziellen und kostenpflichtigen Konkurrenten (wie etwa SPSS) kommt die freie Programmiersprache R ohne grafische Benutzeroberfläche daher. Nach dem Download und der Installation von R ist es deshalb empfehlenswert, zusätzlich einen komfortableren, kostenlosen R-Editor zu installieren.
- RStudio von Posit (<https://posit.co>) ist die wohl am weitesten verbreitete integrierte Entwicklungsumgebung (IDE) für die Programmiersprache R. Weitere nützliche Editoren sind
- Jupyter Notebooks von <https://jupyter.org> oder
- der kostenlose Quelltext-Editor Visual Studio Code von Microsoft (<https://code.visualstudio.com>).
# Datenanalyse
## Pakete laden
R-Pakete sind Sammlungen von Funktionen und Werkzeugen, die von der R-Community entwickelt wurden. Sie erhöhen die Leistungsfähigkeit von R, indem sie bestehende Basisfunktionen verbessern oder neue Funktionen hinzufügen.
Mit der Funktion `install.packages()` werden neue Pakete installiert (z.B. das Paket janitor).
```{r}
#| message: false
#| echo: false
# Pakete laden
library(sysfonts)
library(showtext)
library(corrplot)
library(ggdist)
library(ggExtra)
library(ggforce)
library(ggstatsplot)
library(glue)
library(GWalkR)
library(janitor)
library(paletteer)
library(palmerpenguins)
library(patchwork)
library(psych)
# library(RColorBrewer)
library(readxl)
library(recipes)
library(rjson)
library(scales)
library(skimr)
library(summarytools)
library(statip)
library(tidyAML)
library(TidyDensity)
library(treemap)
# library(waffle)
library(brand.yml)
library(tidyverse)
```
Für die Datenanalyse in sechs Schritten laden Sie bitte folgende Pakete in die aktuelle R-Session:
- corrplot
- ggdist
- ggExtra
- ggforce
- ggstatsplot
- glue
- janitor
- paletteer
- palmerpenguins
- patchwork
- psych
- RColorBrewer
- readxl
- recipes
- rjson
- scales
- skimr
- summarytools
- statip
- tidyAML
- TidyDensity
- tidyverse
- treemap
```{r}
#| include: false
# Schriftart «Manrope» laden
systemfonts::fonts_as_import(family = "Manrope", repositories = "Bunny Fonts")
font_add_google(name = "Manrope", family = "Manrope")
```
```{r}
#| message: false
#| echo: false
# Showtext automatisch für neue Plots verwenden
showtext_auto()
```
## Daten laden
### Beispieldaten
In R stehen zahlreiche Import-Funktionen zur Verfügung, um Daten aus unterschiedlichen Anwendungen und in verschiedensten Formaten zu laden.
Zur Veranschaulichung der verschiedenen Funktionen und Visualisierungen werden die folgenden Datensätze verwendet:
- [Penguins](https://allisonhorst.github.io/palmerpenguins/)\
Die Daten wurden von Dr. Kristen Gorman und der Palmer Station, Antarctica LTER, gesammelt und von Allison Horst in ihrem R-Paket palmerpenguins popularisiert.
- [mtcars](https://www.rdocumentation.org/packages/datasets/versions/3.6.2/topics/mtcars) (Wird ausschliesslich im Abschnitt «[Ausblick auf Machine Learning]» verwendet.)
- [Lernende nach Grossregion, Schulkanton, Geschlecht, Staatsangehörigkeit und Charakter der Schule](https://www.bfs.admin.ch/bfs/de/home/statistiken/kataloge-datenbanken.assetdetail.36430043.html) des Bundesamts für Statistik BFS
- [Lernende nach Grossregion, Schulkanton, Ausbildungsform und Bildungstyp](https://www.bfs.admin.ch/bfs/de/home/statistiken/kataloge-datenbanken.assetdetail.36430044.html) des Bundesamts für Statistik BFS
```{r}
#| message: false
#| echo: false
setwd(dir = "~/Nextcloud/Diverses/Websites/Datenpfad/R/Datenanalyse")
```
```{r}
bgb_staat <-
read_xlsx(path = "data/je-d-15.02.02.01.03.xlsx",
sheet = 1,
col_names = c("Schulkanton", "Total", "Geschlecht_Mann", "Geschlecht_Frau",
"Staatsangehörigkeit_Schweiz", "Staatsangehörigkeit_Ausland",
"Staatsangehörigkeit_Unbekannt", "Charakter der Schule_Öffentlich",
"Charakter der Schule_Privat subventioniert",
"Charakter der Schule_Privat nicht subventioniert"),
trim_ws = TRUE,
skip = 6)
bgb_typ <-
read_xlsx(path = "data/je-d-15.02.02.01.02.xlsx",
sheet = 1,
col_names = c("Schulkanton", "Total", "Ausbildungsform_Vollschulisch",
"Ausbildungsform_Dual", "Typ_EFZ", "Typ_EBA",
"Typ_Nicht BBG-reglementierte berufliche Grundbildung"),
trim_ws = TRUE,
skip = 6)
```
## Deskriptive Statistik
### Explorative Datenanalyse
Die explorative Datenanalyse (Exploratory Data Analysis, abgekürzt EDA) ist ein wesentlicher Schritt in jedem Datenanalyseprojekt. Sie dient der Analyse und Untersuchung von Datensätzen und der deskriptiven Zusammenfassung ihrer wichtigsten Merkmale, wobei oft grafische Darstellungsmethoden verwendet werden. Mit Hilfe von Tabellen, Grafiken und der Ermittlung relevanter Kennzahlen wird versucht, einen Überblick über das gesamte Datenmaterial zu gewinnen, es zu ordnen und zusammenzufassen. Die EDA bildet damit die Grundlage für die weitere Analyse.
### Objekte
Die Funktion `ls()` liefert eine Liste aller bisher gespeicherten Objekte wie Daten und Funktionen.
```{r}
# Gespeicherte Objekte anzeigen
ls()
```
Mit der Funktion `rm()` werden alle unerwünschten Dateien gelöscht.
```{r}
# Unerwünschte Dateien entfernen
rm(bgb_typ)
```
Es ist auch möglich, alle Objekte auf einmal zu entfernen.
```{r}
# Alle Objekte löschen
rm(list = ls())
```
### Datentypen
Ein Datensatz kann Merkmale unterschiedlicher Datentypen enthalten. Einige Daten können Zahlen sein (z.B. Alter oder Gewicht), während andere aus Text bestehen (wie Name oder Adresse). R kennt die folgenden Haupttypen:
- Numerisch: Zahlen, einschliesslich Ganzzahlen (ganze Zahlen) und Dezimalzahlen
- Zeichen: Textstrings, wie Wörter oder Sätze
- Logisch: Wahr- oder Falsch-Werte
- Faktor: Kategoriale Daten mit definierten Stufen (z.B. Farben: rot, grün, blau).
Die Funktion `class()` bietet einen allgemeinen Überblick über den Datentyp, wie z.B. «numerisch» oder «Zeichen».
```{r}
# Datentyp anzeigen
class(penguins$bill_length_mm)
```
Die Funktion `typeof()` zeigt spezifischere Details innerhalb des Datentyps (beispielsweise «double» für Dezimalzahlen in «numerisch»).
```{r}
# Detaillierter Datentyp anzeigen
typeof(penguins$bill_length_mm)
```
### Anfang und Ende
Mit der Funktion `slice_head()` werden die ersten Zeilen bzw. Beobachtungen ausgegeben. In diesem Beispiel wurde die Anzahl auf 10 festgelegt. Der Wert kann jedoch flexibel gewählt werden.
```{r}
slice_head(.data = penguins,
n = 10)
```
Die Funktion `first()` gibt das erste Element eines Eingabevektors zurück.
```{r}
# Erstes Datenelement ausgeben
first(x = penguins)
```
Selbstverständlich ist es in R auch möglich, die letzten Zeilen eines Data Frames (dt. Datenrahmen) auszugeben. Die Funktion `slice_tail()` gibt die letzten n Zeilen eines Datenrahmens zurück (Standardwert ist 6).
```{r}
slice_tail(.data = penguins,
n = 5)
```
Verwenden Sie `slice_tail(1)`, um nur die letzte Zeile zu erhalten.
```{r}
slice_tail(.data = penguins,
n = 1)
```
Die Funktion `last()` ergänzt die Funktion `first()`, indem sie ebenfalls das letzte Element eines Vektors zurückgibt.
```{r}
# Letztes Datenelement ausgeben
last(x = penguins)
```
Mit der Funktion `slice()` von dplyr können bestimmte Zeilen ausgewählt werden. Um die vorletzte Zeile zu bekommen, verwenden Sie `n()` -1.
```{r}
slice(.data = penguins,
n() - 1)
```
Wenn Sie statt der ersten oder letzten Zeile eine zufällige Auswahl von Zeilen ausgeben möchten, steht Ihnen dafür die Funktion `slice_sample()` zur Verfügung.
```{r}
slice_sample(.data = penguins,
n = 5)
```
Mit der Funktion `nth()` kann ein Vektorelement an einer beliebigen Stelle innerhalb des Vektors extrahiert werden. Durch Angabe des entsprechenden Elements erhalten Sie die gewünschte Ausgabe.
```{r}
nth(x = penguins,
n = 7)
```
Durch das Voranstellen eines Minuszeichens vor die Position lassen sich Elemente vom Ende des Vektors abrufen.
```{r}
nth(x = penguins,
n = -7)
```
Die Funktion `slice_max()` des dplyr-Pakets ermöglicht eine intuitive Auswahl des maximalen Werts. Für den minimalen Wert steht `slice_min()` zur Verfügung.
```{r}
slice_max(.data = penguins,
order_by = bill_length_mm,
n = 5)
```
Es ist auch möglich, alle Namen der Spalten auszugeben.
```{r}
# Spaltennamen ausgeben
names(penguins)
```
### Umfang
```{r}
#| message: false
#| echo: false
bgb_staat <-
read_xlsx(path = "data/je-d-15.02.02.01.03.xlsx",
sheet = 1,
col_names = c("Schulkanton", "Total", "Geschlecht_Mann", "Geschlecht_Frau",
"Staatsangehörigkeit_Schweiz", "Staatsangehörigkeit_Ausland",
"Staatsangehörigkeit_Unbekannt", "Charakter der Schule_Öffentlich",
"Charakter der Schule_Privat subventioniert",
"Charakter der Schule_Privat nicht subventioniert"),
trim_ws = TRUE,
skip = 6)
bgb_typ <-
read_xlsx(path = "data/je-d-15.02.02.01.02.xlsx",
sheet = 1,
col_names = c("Schulkanton", "Total", "Ausbildungsform_Vollschulisch",
"Ausbildungsform_Dual", "Typ_EFZ", "Typ_EBA",
"Typ_Nicht BBG-reglementierte berufliche Grundbildung"),
trim_ws = TRUE,
skip = 6)
```
Interessieren Sie sich für den Umfang Ihres Datensatzes? Die Basisfunktion `dim()` liefert die Anzahl der Zeilen und Spalten.
```{r}
# Umfang des Datensatzes
dim(penguins)
```
Sobald die Daten geladen sind, können Sie mit `names()` oder `colnames()` die Variablennamen überprüfen.
```{r}
# Variablennamen prüfen
names(penguins)
```
Der gesamte Datensatz kann mit der Funktion `View()` angezeigt werden. Die Darstellung ähnelt der von Microsoft Excel.
```{r}
# Datensatz anzeigen
View(penguins)
```
Während `View()` eine Excel-ähnliche Darstellung bietet, ermöglicht die Funktion `fix()` das Editieren von Datenzellen vergleichbar wie in Excel.
```{r}
# Datenzellen editieren
fix(penguins)
```
Mit `glimpse()` können Sie eine transponierte Version des Datenrahmens anzeigen, bei der die Spalten vertikal und die Daten horizontal dargestellt werden. `glimpse()` zeigt die Dimension des Datenrahmens und der zugrunde liegende Datentyp jedes Merkmals.
```{r}
# Zusammenfassung der wichtigsten Kennzahlen in transponierter Form
glimpse(penguins)
```
Alternativ kann die Struktur der Daten auch mit der Funktion `str()` ermittelt werden.
```{r}
# Datenstruktur anzeigen
str(penguins)
```
### Masse der zentralen Tendenz
Um die Verteilung der Daten besser zu verstehen, können Sie die so genannten Masse der zentralen Tendenz untersuchen, welche statistisch die Mitte der Daten beschreibt. Ziel ist es, einen typischen Wert zu finden. Gängige Methoden zur Bestimmung der Datenmitte sind:
- Mittelwert: Ein einfacher Durchschnittswert, der berechnet wird, indem alle Werte des Stichprobensatzes addiert und dann die Gesamtsumme durch die Anzahl der Stichproben dividiert wird.
- Median: Der Wert, der in der Mitte des Bereichs aller Stichprobenwerte liegt.
- Modus: Der am häufigsten vorkommende Wert in der Stichprobenmenge.
```{r}
mean(penguins$body_mass_g,
# Argument na.rm = TRUE ergänzen, um fehlende Werte für die Berechnung auszuschliessen
na.rm = TRUE)
median(penguins$body_mass_g,
na.rm = TRUE)
mean_weight <- mean(penguins$body_mass_g, na.rm = TRUE)
median_weight <- median(penguins$body_mass_g, na.rm = TRUE)
cat("Mittelwert:", mean_weight, "\nMedian:", median_weight)
mfv(penguins$body_mass_g,
na_rm = TRUE)
head(table(penguins$body_mass_g),
n = 10)
```
Mithilfe der Funktion `colMeans()` von Base R können die Mittelwerte mehrerer metrischer Vektoren gleichzeitig berechnet werden. Für die Zeilen gibt es die entsprechende Funktion `rowMeans()`.
```{r}
colMeans(x = penguins[, 3:6],
na.rm = TRUE)
```
#### Apply-Familie
Schleifen sind grossartig, aber für sich wiederholende Aufgaben mit Datenstrukturen ist die Vektorisierung unschlagbar. Sie ist schneller, sauberer und ermöglicht es Ihnen, sich auf das «Was» statt auf das «Wie» Ihrer Analyse zu konzentrieren. Hier kommt die Apply-Funktion ins Spiel.
Der Mittelwert (FUN) wird mit `lapply()`auf die ausgewählten Spalten angewendet und als Liste zurückgegeben.
```{r}
lapply(X = na.omit(penguins[, 3:6]),
FUN = mean)
```
`sapply()` ist vergleichbar mit `lapply()`, versucht aber die Ausgabe zu vereinfachen. Sind alle Ergebnisse vom gleichen Typ (z.B. numerisch), ist die Rückgabe ein Vektor anstelle einer Liste.
```{r}
sapply(X = na.omit(penguins[, 3:6]),
FUN = mean)
```
Mit `apply()` wird eine eigene Funktion auf alle ausgewählten Spalten angewendet.
```{r}
# Spannweite (Range) berechnen
apply(X = na.omit(penguins[, 3:6]),
MARGIN = 2,
FUN = function(every_column){max(every_column)-min(every_column)})
```
Weitere Apply-Funktionen finden Sie im Abschnitt «[Häufigkeitstabellen]».
### Streuungsmasse
Wie gross ist die Variabilität in den Daten? Zu den typischen Statistiken, welche die Variabilität messen, gehören:
- Spannweite (Range): Die Differenz zwischen dem Maximum und Minimum. Dafür gibt es keine eigene Funktion, aber sie lässt sich leicht mit den Funktionen `min()` und `max()` berechnen. Ein anderer Ansatz ist die Verwendung der Funktion `range()` von Base R, welche einen Vektor zurückgibt, der das Minimum und Maximum aller angegebenen Argumente enthält. Wenn Sie diese mit `diff()` umschliessen, können Sie die Spannweite berechnen.
- Interquartilsabstand (IQR): Zur Berechnung wird eine Stichprobe nach Grösse sortiert und das 25%-Quartil vom 75%-Quartil subtrahiert. In R können Sie dazu die Funktion `IQR()` aus dem stats-Paket verwenden. Im Gegensatz zur Spannweite können so Ausreisser, die das Ergebnis verzerren, umgangen werden.
- Varianz: Entspricht dem Mittelwert der quadrierten Differenz zum Mittelwert. Sie können die eingebaute Funktion `var()` verwenden, um die Varianz zu ermitteln.
- Standardabweichung: Entspricht der Quadratwurzel der Varianz. Sie können die integrierte Funktion `sd()` verwenden, um die Standardabweichung zu finden.
- Variationskoeffizient: Dieser ist neben der Varianz und der Standardabweichung ein weiteres Streuungsmass der deskriptiven Statistik. Als relatives Streuungsmass bzw. normierte Standardabweichung hängt der Variationskoeffizient (`sd()` / `mean()`) im Gegensatz zu den beiden anderen Kennzahlen nicht von der Masseinheit der statistischen Variable ab. Der Variationskoeffizient ist jedoch nur sinnvoll für Messreihen mit ausschliesslich positiven (oder ausschliesslich negativen) Werten.
Die Position des grössten Wertes kann mit `which.max()` ermittelt werden. Für das Minimum gibt es das entsprechende Pendant mit `which.min()`.
```{r}
max(penguins$bill_length_mm, na.rm = TRUE)
which.max(penguins$bill_length_mm)
```
#### map
Durch die Verwendung der `map()`-Funktion des Pakets purrr können Sie viele for-Schleifen durch Code ersetzen, der sowohl kürzer als auch einfacher zu lesen ist.
```{r}
# Spalten auswählen, um das Mass der Varianz zu analysieren
cols <- penguins |>
select(c(bill_length_mm, bill_depth_mm)) |>
drop_na()
```
```{r}
# Eine Funktion auf jede Spalte anwenden
map(cols, function(column) {
range <- diff(range(column)) # dasselbe wie: max(Spalte) - min(Spalte)
var <- var(column)
std <- sd(column)
glue(
'- Spannweite: {format(round(range, 2), nsmall = 2)}
- Varianz: {format(round(var, 2), nsmall = 2)}
- Standardabweichung: {format(round(std, 2), nsmall = 2)}',
.sep = '\n'
)
})
```
`map()` bietet darüber hinaus einen konsistenten und gut lesbaren Ansatz für das Iterieren über Listen.
```{r}
# Eine Funktion auf jedes Listenelement anwenden
list_1 <- list(1, 2, 3)
map(.x = list_1, .f = ~.x^2) # Alternative: map(.x = list_1, .f = function(x) x^2)
```
Wenn Sie über mehrere Listen gleichzeitig iterieren müssen, sind `map2()` und `pmap()` hilfreich.
```{r}
#
list_2 <- list("Waadt", "Genf", "Wallis")
map2(.x = list_1,
.y = list_2,
.f = ~paste0("Bei der Anzahl Lehrverhältnisse nimmt der Kanton ",
.y,
" den ",
.x,
". Platz ein."))
```
#### quantile
Mit `quantile()` kann man die Streuung bzw. die Quantile einer Variablen bestimmen.
```{r}
# Streuung von Variablen darstellen
quantile(penguins$bill_length_mm, na.rm = TRUE)
```
```{r}
# Eigene Werte definieren
probs <- c(0.01, 0.25, 0.5, 0.75, 0.99)
penguins |>
drop_na() |>
group_by(species) |>
summarise(Quantil = list(probs),
"Schnabellänge" = list(quantile(x = bill_length_mm, probs = probs))) |>
unnest(cols = c(Quantil, "Schnabellänge"))
```
### Doppelte Werte
Es ist immer möglich, dass Datensätze doppelte Einträge aufweisen. Deshalb ist es wichtig, dies zu prüfen.
```{r}
# Duplikate im Datensatz prüfen
any(penguins[duplicated(penguins), ])
```
```{r}
# Duplikate in bestimmten Spalten prüfen
any(duplicated(x = penguins$species))
```
```{r}
# Duplikate in mehreren Spalten prüfen
any(duplicated(x = penguins[c("species", "island")]))
```
```{r}
# NA-Werte vom Vergleich ausschliessen
# duplicated(x = penguins, incomparables = NA)
```
Nach der Identifizierung von Dubletten besteht der nächste Schritt oft darin, diese zu entfernen.
```{r}
# Duplikate entfernen mit «duplicated»
ergebnis <- (penguins[!duplicated(penguins), ])
head(ergebnis)
```
```{r}
# Duplikate schnell entfernen mit «unique»
ergebnis <- unique(x = penguins)
head(ergebnis)
```
### Kennwerte zusammenfassen
Die Funktion `summary()` ermöglicht einen Überblick zu den wichtigsten Kennzahlen eines Datensatzes. Bei numerischen Merkmalen umfassen diese Minimum, 1. Quartil, Median, Mittelwert, 3. Quartil und Maximum.
```{r}
# Zusammenfassung der wichtigsten Kennzahlen
summary(penguins)
```
Die Funktion `describe()` des Pakets psych liefert ebenfalls eine Zusammenfassung der deskriptiven Statistik. Sie enthält neben den üblichen Lagemassen auch Werte für Schiefe und Kurtosis.
```{r}
describe(penguins$bill_length_mm,
na.rm = TRUE)
```
Mit der Funktion `summarise()` können beliebige Kennwerte ausgegeben werden. Beispielsweise können Sie das arithmetische Mittel (Mittelwert) und den Median einer numerischen Variablen finden.
```{r}
summarise(.data = penguins,
"Mittelwert Gewicht" = mean(body_mass_g, na.rm = TRUE),
"Median Gewicht" = median(body_mass_g, na.rm = TRUE))
```
#### summarytools
Das R-Paket summarytools vereinfacht den Prozess der Datenexploration, indem es Funktionen bereitstellt, die mit minimalem Code umfangreiche Zusammenfassungen Ihrer Daten erzeugen.
Die Funktion `dfSummary()` liefert eine detaillierte Zusammenfassung, einschliesslich
- Datentypen
- Fehlende Werte
- Eindeutige Werte
- Grundlegende Statistiken
- Grafische Darstellungen
```{r}
dfSummary(x = penguins,
graph.col = TRUE,
graph.magnif = 0.75,
style = "grid") # |> stview() Interaktiver HTML-Bericht
```
Verwenden Sie die Funktion `descr()`, um detaillierte deskriptive Statistiken für Ihre numerischen Variablen zu erhalten. Sie können auswählen, welche Statistiken generiert werden sollen (z.B. «common», «fivenum», usw.).
```{r}
descr(x = penguins,
stats = "fivenum")
```
Für kategoriale Variablen erzeugt die Funktion `freq()` Häufigkeitstabellen, welche die Verteilung der Kategorien zeigen. Dies kann Ihnen helfen, die Verteilung und Häufigkeit jeder Kategorie in Ihren Daten zu verstehen.
```{r}
# Häufigkeitsstatistik
freq(x = penguins)
```
Die explorative Datenanalyse (EDA) ist entscheidend, um Ihre Daten zu verstehen, Trends zu erkennen und Probleme aufzuspüren, bevor Sie ausführlichere Analysen durchführen. Ohne die richtigen Werkzeuge kann EDA jedoch zeitaufwendig sein. Mit [InsightR](https://dtavis.shinyapps.io/insightr/) steht Ihnen eine schnellere und effizientere Methode zur Verfügung, um Ihre Daten zu analysieren und statistische Kennwerte zusammenzufassen.
#### skimr
Die Kernfunktion von skimr ist `skim()`, die für die Arbeit mit (gruppierten) Datenrahmen entwickelt wurde. Wie `summary()` zeigt `skim()` Statistiken bzw. Ergebnisse für jede Spalte.
```{r}
# Zusammenfassung der wichtigsten Kennzahlen und fehlenden Werte
skim(penguins)
```
#### GWalkR
Ein neuer Ansatz zur explorativen Datenanalyse in R ist das Paket «[GWalkR](https://github.com/Kanaries/GWalkR)». Es kombiniert das Paket «htmlwidgets» mit der JavaScript-Bibliothek «Graphic Walker» und verwandelt so den Datenrahmen in eine Tableau-ähnliche Drag&Drop-Benutzeroberfläche. Für alle, die bereits mit Datenvisualisierungssoftware wie Microsoft Power BI oder Tableau gearbeitet haben, bietet GWalkR einen intuitiven Einstieg in die Datenanalyse mit R.
```{r}
#| message: false
#| echo: false
# Tableau-ähnliche explorative Datenanalyse
# gwalkr(penguins)
```
#### Weitere Pakete
Weitere umfassende und teilweise interaktive Einblicke in importierte Datensätze liefern die nachfolgenden Pakete. Diese bieten unter anderem auch eine erste gute Zusammenfassung der fehlenden Werte (n_missing).
- [esquisse](https://cran.r-project.org/web/packages/esquisse/vignettes/get-started.html): RStudio-Add-In für interaktive Datenvisualisierung
- [radiant](https://radiant-rstats.github.io/docs/): Browserbasierte Schnittstelle für Analysen in R, basierend auf dem shiny-Paket
- [explore](https://cran.r-project.org/web/packages/explore/vignettes/explore.html): Vereinfacht die explorative Datenanalyse für bivariate Analysen
- [dataxray](https://agstn.github.io/dataxray/): Interaktive Tabellenschnittstelle für Zusammenfassungen von Daten
### Häufigkeitstabellen
#### table
Die Arbeit mit Häufigkeitstabellen ist eine typische Aufgabe in der Datenanalyse. R bietet hierfür mehrere Möglichkeiten. Wenn Sie z.B. wissen möchten, wie viele Pinguine auf den drei Inseln untersucht wurden, können Sie die Funktion `table()` verwenden. Den prozentualen Anteil erhält man mit `prop.table()`.
```{r}
# Tabelle ausgeben
table(penguins$island)
```
```{r}
# Prozentwerte ausgeben
round(x = prop.table(table(penguins$island)) * 100,
digits = 2)
```
Mit den Argumenten `margin = 1` oder `margin = 2` können die relativen Zeilen- oder Spaltenprozentsätze berechnet werden.
```{r}
# Prozentwerte pro Zeile
round(x = prop.table(table(penguins$species,
penguins$island),
margin = 1) * 100,
digits = 2)
```
```{r}
# Prozentwerte pro Spalte
round(x = prop.table(table(penguins$species,
penguins$island),
margin = 2) * 100,
digits = 2)
```
Die Funktion `addmargins()` fügt die Randsummen hinzu.
```{r}
# Randsummen ausgeben
addmargins(table(penguins$species,
penguins$island))
```
Manchmal ist es sinnvoll, die Tabelle zu transponieren (Spalten und Zeilen zu tauschen).
```{r}
table(penguins$species,
penguins$sex)
# Transponierte Tabelle
t(table(penguins$species,
penguins$sex))
```
#### count
Die Ausgabe der Absolutwerte ist auch mit Hilfe der Funktion `count()` möglich.
```{r}
count(x = penguins,
species,
island,
sort = TRUE)
```
#### xtabs
Die Funktion `xtabs()` bietet eine flexible und leistungsstarke Möglichkeit, Häufigkeits- und Summentabellen in R zu erstellen. Dank ihrer Formelschnittstelle ist sie besonders praktisch bei der Arbeit mit Datenrahmen. Für komplexere Aggregationen wie Mittelwerte oder Mediane muss sie jedoch mit anderen Funktionen, wie z.B. wie `ftable()`, kombiniert werden.
Ein grosser Vorteil von `xtabs()` gegenüber `table()` ist, dass die Funktion gut mit Datenrahmen zusammenarbeitet. Es ist nicht nötig, einzelne Spalten zu extrahieren.
```{r}
# Häufigkeitstabelle
xtabs(formula = ~ species + sex, # Variablen rechts von ~, um Häufigkeiten zu zählen
data = penguins,
na.action = na.pass) # Standardwert; NA mit Wert 0 in Tabelle aufnehmen
```
```{r}
# Tabelle mit mehreren Dimensionen
by(data = penguins, INDICES = penguins$island, FUN = function(subset) {
xtabs(formula = ~ species + sex,
data = subset)
})
```
Manchmal müssen Sie nicht nur Häufigkeiten zählen, sondern auch Werte summieren. Setzen Sie dazu eine numerische Variable auf die linke Seite der Formel.
```{r}
# Summentabelle
print("Summierte Schnabellänge pro Pinguinart")
xtabs(formula = bill_length_mm ~ species,
data = penguins,
na.rm = TRUE)
```
### Grafische Darstellung
Grafische Darstellungen ermöglichen eine schnelle und einfache Interpretation von Daten, indem sie Trends und Muster visuell hervorheben. Zudem bieten sie einen klaren Überblick über grosse Datenmengen und erleichtern es, wichtige Informationen auf einen Blick zu erfassen. Sie unterstützen die effektive Kommunikation komplexer Daten, was besonders in Präsentationen und Berichten nützlich ist.
Die Funktion `colors()` gibt einen Vektor zurück, der alle in R eingebauten Farbnamen in alphabetischer Reihenfolge enthält, wobei das erste Element «white» ist. So lassen sich schnell passende Farben für das Diagramm finden.
```{r}
head(colors(), n = 20)
```
#### Säulendiagramm
Das Säulendiagramm dient dazu, die Werte unterschiedlicher Kategorien oder Gruppen gegenüberzustellen. Auf der x-Achse sind die Kategorien oder Gruppen dargestellt, während die y-Achse die entsprechenden Werte anzeigt.
```{r}
# Nominalskalierte (kategoriale) oder metrische Variable
plot(penguins$species,
col = "grey",
border = NA,
ylim = c(0, 200))
```
```{r}
# Häufigkeitstabellen mit der Plotfunktion von Base R darstellen
barplot(table(penguins$species),
col = "grey",
border = NA,
main = "Häufigkeitstabelle",
ylim = c(0, 200))
```
```{r}
# Gruppiertes Säulendiagramm
barplot(prop.table(table(penguins$species,
penguins$sex),
margin = 2),
legend.text = TRUE,
beside = TRUE,
xlim = c(0, 11),
ylim = c(0, 0.5))
```
```{r}
# Mittlere Schnabellänge für die drei Pinguinarten berechnen
mittlere_schnabellaenge <-
tapply(X = penguins$bill_length_mm,
INDEX = penguins$species,
FUN = mean, na.rm = TRUE)
# Säulen mit unterschiedlichen Farben
barplot(mittlere_schnabellaenge,
col = c("#9FC131", "#93257B", "#57AF2C"),
ylim = c(0, 50))
```
#### Histogramm
Manchmal sagt ein Bild mehr als tausend Worte. Wenn Datenwissenschaftler eine Variable untersuchen, beispielsweise eine Stichprobe des Gewichts von Pinguinen, interessiert sie die Verteilung dieser Variable. Das heisst, sie wollen wissen, wie die verschiedenen Werte in der Stichprobe verteilt sind. Oft ist die Visualisierung der Daten in Form eines Histogramms der Ausgangspunkt für diese Untersuchung. Dabei werden auf der x-Achse die Werte des Datensatzes und auf der y-Achse die Häufigkeit, also wie oft jeder Wert im Datensatz vorkommt, abgebildet.
```{r}
hist(x = penguins$body_mass_g,
breaks = 20,
col = "grey",
border = "white",
main = "Gewichtsverteilung der Pinguine",
xlim = c(2000, 7000),
ylim = c(0, 50),
xlab = "Gewicht in Gramm",
ylab = "Häufigkeit")
```
#### Dichteplot
Der Dichteplot ist eine grafische Darstellung der Verteilung einer numerischen Variablen und verwendet die Kerndichteschätzung, um eine glatte Kurve zu erzeugen. Dies ermöglicht eine kontinuierliche und detaillierte Ansicht der Datenverteilung im Vergleich zu einem Histogramm.
```{r}
options(scipen = 999)
plot(density(x = penguins$body_mass_g,
na.rm = TRUE))
```
#### Boxplot
Ein Boxplot, auch Box-and-Whisker-Plot genannt, ist ein Diagramm zur grafischen Darstellung von Datenverteilungen. Er zeigt den Median, die Quartile und mögliche Ausreisser, wodurch man schnell einen Überblick über die Verteilung und Streuung der Daten erhält.
```{r}
boxplot(penguins$body_mass_g ~ penguins$species)
```
```{r}
boxplot(penguins$bill_length_mm,
penguins$bill_depth_mm,
names = c("Schnabellänge", "Schnabeltiefe"))
```
#### Streudiagramm
Das Streudiagramm, auch Scatterplot genannt, ist ein Diagramm, das die Beziehung zwischen zwei Variablen darstellt. Jeder Punkt im Diagramm repräsentiert ein Datenpaar, wodurch Muster, Trends oder Korrelationen zwischen den Variablen sichtbar werden.
```{r}
plot(penguins$bill_depth_mm, penguins$bill_length_mm,
main = "Gegenüberstellung von Schnabeltiefe und Schnabellänge")
```
#### Streumatrix
Die Funktion `pairs.panels()` erstellt eine Streumatrix, welche die paarweisen Beziehungen zwischen mehreren Variablen in einem Datensatz darstellt. Jede Zelle der Matrix zeigt ein Streudiagramm für ein Variablenpaar, was es ermöglicht, Muster und Korrelationen zwischen allen Variablen gleichzeitig zu erkennen.
```{r}
pairs.panels(x = penguins[3:6],
pch = 21,
hist.col = "#93257B",
line.col = "#9FC131")
```
Ein Streumatrixdiagramm, bestehend aus Histogrammen und Trendlinien, können Sie auch mit der Funktion `pairs()` erstellen und so Zusammenhänge sichtbar machen.
```{r}
#| echo: false
panel_hist <- function(x, ...)
{
usr <- par("usr"); on.exit(par(usr))
par(usr = c(usr[1:2], 0, 1.5) )
h <- hist(x, plot = FALSE)
breaks <- h$breaks; nB <- length(breaks)
y <- h$counts; y <- y/max(y)
rect(breaks[-nB], 0, breaks[-1], y, col = "#93257B", ...)
}
```
```{r}
#| warning: false
pairs(x = penguins[3:6],
main = "Streumatrix",
panel = panel.smooth,
cex = 1,
pch = 21,
bg = "#9FC131",
diag.panel = panel_hist,
cex.labels = 1.5,
font.labels = 2)
```
Die Funktion `ggpairs()` aus dem Paket GGally visualisiert ebenfalls paarweise Beziehungen.
## Datenaufbereitung
### Daten bereinigen
Die Bedeutung der Datenbereinigung wird häufig unterschätzt. Dabei ist sie ein grundlegender Schritt für eine erfolgreiche Datenanalyse. In vielen Fachportalen und Artikeln wird darauf hingewiesen, dass die Datenbereinigung nach dem Pareto-Prinzip ca. 80% der Zeit einer Datenanalyse in Anspruch nimmt und die eigentliche Analyse nur 20%.
Nachdem Sie Ihre Rohdaten importiert und sich einen ersten Überblick verschafft haben, ist es immer eine gute Idee, diese zu bereinigen. Dadurch werden Fehler und andere Probleme reduziert. Dabei werden fehlerhafte Datenpunkte entfernt oder die Daten in ein nützlicheres Format konvertiert. In anderen Situationen können Datenpunkte, die deutlich ausserhalb des erwarteten Bereichs liegen, auch Ausreisser genannt, manchmal aus Analysen entfernt werden. Dies sollte jedoch sorgfältig geprüft werden, um sicherzustellen, dass keine Datenpunkte gelöscht werden, die echte Informationen liefern.
#### janitor
Bestehende Spaltennamen sind oftmals intuitiv und leicht verständlich, aber nicht unbedingt einfach im Code zu handhaben. Mit der Funktion `clean_names()` aus dem Paket janitor können Sie Spaltennamen mühelos bereinigen. Sie können wählen, ob Sie alle Namen in Snake Case (alle Wörter klein geschriebenen, getrennt durch Unterstriche), Variationen von Camel Case (Grossbuchstaben zwischen den Wörtern), Title Case oder andere Stile ändern möchten. Weiter werden Leerzeichen in \_ umgewandelt und Klammern entfernt. Auf diese Weise sind die Spaltenbezeichnungen leicht verständlich und gut im Code zu verarbeiten.
Datensätze mit leeren oder überflüssigen Zeilen oder Spalten sind keine Seltenheit. Dies gilt insbesondere für Excel-Dateien, die viele leere Zellen enthalten. Diese können mit der Funktion `remove_empty()` entfernt werden. Ohne Argument werden standardmässig sowohl Zeilen als auch Spalten mit `remove_empty()` gelöscht. Das kann man anpassen, indem man z.B. which = «rows» oder which = «cols» verwendet.
```{r}
#| message: false
#| echo: false
bgb_staat_clean <- bgb_staat |>
clean_names() |> # Das Argument "replace =" ermöglicht benutzerdefinierte Ersatzwerte.
remove_empty(which = c("rows", "cols"))
```
```{r}
#| message: false
#| echo: false
#| warning: false
bgb_staat_clean <- bgb_staat_clean |>
subset(select = total:charakter_der_schule_privat_nicht_subventioniert) |>
mutate(across(where(is.character), as.numeric)) |>
cbind(bgb_staat_clean$schulkanton) |>
rename(schulkanton = 'bgb_staat_clean$schulkanton')
```
```{r}
bgb_typ_clean <- bgb_typ |>
clean_names() |>
remove_empty(which = c("rows", "cols"))
```
```{r}
#| warning: false
# Numerische Vektoren transformieren
bgb_typ_clean <- bgb_typ_clean |>
subset(select = total:typ_nicht_bbg_reglementierte_berufliche_grundbildung) |>
mutate(across(where(is.character), as.numeric)) |>
cbind(bgb_typ_clean$schulkanton) |>