-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path05_datenimport.Rmd
673 lines (517 loc) · 45.6 KB
/
05_datenimport.Rmd
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
## **Datenimport**
[![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/deed.de)
*"Datenimport" von David Schweizer, Nina Hauser, Frie Preu, Philipp Bosch in "R Lernen - der Datenkurs von und für die Zivilgesellschaft" von CorrelAid e.V. Lizensiert unter [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/deed.de).*
Diese Woche geht es darum, wie Ihr Daten in R-Studio importieren könnt. In den Kapiteln ganz unten auf der Seite (Exkurse 1 - 3) werden komplexere Themen eingeführt. Schaut Euch diese je nach Bedarf oder auch nach Ende des Kurses an - sie sind aber definitiv kein Muss!
![*Video: Datenimport und APIs (30min)*](https://youtu.be/NA9QLeQsE9M)
### **Kernaussagen**
- Es gibt **zwei grundlegende Möglichkeiten**, Daten zu importieren:
1. aus lokal oder remote gespeicherten **Dateiformaten** (XLSX, CSV, ...)
2. über **Datenabfragen** von Datenbanken und aus dem Internet (Abfragesprachen wie SQL oder über APIs und Web-Scraping; mehr hierzu in den Exkursen)
- Um Dateien richtig importieren zu können, ist es wichtig, herauszufinden, welches **Dateiformat** die Datei hat:
- **Windows-User** können sich die Dateiendung über die Multifunktionsleiste auf der Registerkarte "Ansicht" anzeigen lassen: Aktiviert dort das Feld "Dateinamenerweiterungen" im Abschnitt "Ein-/Ausblenden"
- **Mac-User** navigieren zu ihrem Schreibtisch und können sich dort die Dateiendung über "Finder" -> "Erweitert" -> Alle Dateinamensuffixe einblenden" anzeigen lassen
- Um Fehlern vorzubeugen, solltet Ihr die **Datei vorab in einem Texteditor öffnen** (nicht immer möglich) und dabei folgendes beachten:
1) In welchem **Dateiformat** liegt die Datei vor?
2) Wo ist die Datei **gespeichert**?
3) Was gibt es hinsichtlich **Dateistruktur** zu beachten (Separatoren, fehlende Werte, etc.)?
4) Wenn Ihr **deutschsprachige Dateien** importiert, müsst Ihr umso mehr auf Umlaute, Spaltentrenner (engl. Separator, im Deutschen ";") und Dezimaltrennzeichen (im Deutschen ",") achten. Hier besteht großes Fehlerpotential, da die meisten Datenanalyseprogramme die englische Sprache als Standardeinstellung haben.
- Der Import von CSV-, XLSX-, SPSS-, SAS und Stata-Dateien kann in RStudio **ohne Code** über "File" -> "Import Dataset" erfolgen
- Alternativ können wir diese Dateien auch mit Funktionen diverser Packages importieren
**Überblick über die verschiedenen Dateiformate:**
```{r dateiformate_tabelle, results='asis'}
tabelle <- "
Dateiformat: | Dateistruktur: | Endung: | Package::Funktion
--------------|-------------------------------------------------------------------|---------------------------------|------------
CSV-Datei | tabellarisch-strukturierte Textdatei | .csv | readr::read_csv
Excel-Datei | tabellarische Daten aus Microsoft Excel | .xls/.xlsx | readxl::read_excel
SAS | SAS-Export, der nicht in allen Anwendungen geöffnet werden kann | .sas | haven::read_sas
Shapefile | Kartographische Datei, die Koordinaten und Polygone enthält | .shp | sf::st_read
SPSS | SPSS-Export, der nicht in allen Anwendungen geöffnet werden kann | .sav | haven:: read_sav
Stata | Stata-Export, der nicht in allen Anwendungen geöffnet werden kann | .dta | haven::read_dta
Textdatei | allgemeine Textdateien | .txt | readr::read_delim
"
cat(tabelle)
```
### **Quiz**
```{r quiz_datenimport, echo=FALSE}
quiz(caption = NULL,
question("Welche Faktoren spielen beim Datenimport eine wichtige Rolle?",
answer("Das Dateiformat (erkennbar an der Dateiendung)", correct = TRUE),
answer("Die Dateistruktur mit Codierung, (Dezimal-)Trennzeichen, uvm.", correct = TRUE),
answer("Der Speicherort (lokal oder remote)", correct = TRUE),
answer("Die Art und Weise wie die Daten geladen werden sollen (einmalig, periodisch oder live)", correct = TRUE),
correct = "Richtig!",
incorrect = "Leider falsch: Alle vier Faktoren sind wichtig.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("An welcher Dateiendung erkennt Ihr Excel-Dateien?",
answer(".xls", correct = TRUE),
answer(".xlsx", correct = TRUE),
answer(".csv"),
correct = "Richtig!",
incorrect = "Leider falsch: Excel-Dateien enden mit .xls oder .xlsx. CSV-Dateien sind Textdateien - aber Ihr könnt sie natürlich in Excel öffnen.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("Woran erkennt Ihr CSV-Dateien?",
answer('An dem Trennzeichen ","'),
answer('An der Dateiendung ".csv"', correct = TRUE),
correct = "Richtig!",
incorrect = "Leider falsch: CSV-Dateien sind zwar in der Regel durch Kommata getrennt, es gibt allerdings auch CSV-Dateien, deren Spalten durch Semikolons, Pipes (senkrechte Striche) und Tabstopps getrennt werden.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("Welche Optionen habt Ihr, lokale Dateien zu importieren?",
answer("Manuell über den File Explorer in RStudio (File -> Import Dataset)", correct = TRUE),
answer("Mit individuellen Funktionen aus verschiedenen Packages für die verschiedenen Dateiformate", correct = TRUE),
answer("SAS- und SPSS-Dateien können mit der gleichen Funktion importiert werden"),
correct = "Richtig!",
incorrect = "Leider falsch: Wir benötigen unterschiedliche Funktionen, die jedoch mit dem gleichen Package geladen werden können.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("Können nur lokal gespeicherte Dateien importiert werden?",
answer("Ja"),
answer("Nein", correct = TRUE),
correct = "Richtig!",
incorrect = "Leider falsch: Auch das Laden von Dateien über Hyperlinks ist beispielsweise möglich.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
)
)
```
### **Interaktive Übung**
Im restlichen Kapitel üben wir den Import von unterschiedlichen CSV- und XLSX-Dateien.
##### **CSV-Dateien**
Eine CSV-Datei (comma separated values, zu dt. Komma getrennte Werte) ist eine Datei, in der die verschiedenen Datenwerte durch Kommata getrennt sind. Grundsätzlich entspricht **jede Zeile** einer **Beobachtung**. Die erste Zeile enthält allerding keine Werte, sondern die **Bezeichnungen für die entsprechende Spalte**. Sie wird **Header** genannt. Wir nutzen sie, um auf bestimmte Spalten und Werte zuzugreifen.
Wir können die `read.csv()`-Funktion des `readr`-Packages nutzen, um CSV-Dateien zu importieren. Diese hat verschiedene Argumente, welche wir entsprechend unserer Dateistruktur setzen können:
``` {r exericse_csv, exercise = TRUE}
# install.packages("readr")
# Komma als Separator und Punkt als Dezimaltrennzeichen als Standard
data_raw <- readr::read_csv(
file = 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-01-26/plastics.csv', # Dateiname/Pfad zur Datei
col_names = TRUE, # Vorhandensein des Headers
skip = 0, # Festlegen, ob Zeilen übersprungen werden sollen
na = c("", "NA") # Definition, wie "NA"-Werte aussehen z.B. "" (leer), festlegen
)
head(data_raw)
```
Daten können sowohl über (offene) URLs (Uniform Resource Locator, zu dt. Link) als auch über lokale Dateipfade importiert werden. Ersteres funktioniert für die meisten Packages intuitiv (siehe oben). Lesen wir Dateien ein, die lokal gespeichert sind, müssen wir den Path definieren. Dazu gibt es verschiedene Methoden, von denen jedoch nur eine wirklich sinnvoll ist: Arbeiten wir an Analysen in R, legen wir sowohl unser Skript als auch unsere Daten in einem dafür vorgesehenen **Ordner** ab, der "daten" heißt. Zu diesem Speicherort navigieren wir mithilfe der Funktion `here::here()`.
``` {r daten_einlesen_lokal, exercise = TRUE}
# Alternative für lokale Dateien, die in Eurem R-Projekt als CSV-Datei in einem Ordner namens "Daten hinterlegt wurden, mit dem "here"-Package (hier nur zum Zeigen)
data_processed <- readr::read_csv(here::here('daten/bffp2019_plastics_processed.csv'))
head(data_processed)
```
Aber Achtung: Wer **Programme** (insb. Excel) in **deutscher Sprache** nutzt, exportiert CSV-Dateien häufig mit dem Separator ";" und dem Dezimal-Trennzeichen ",". Das führt zu Fehlern. Deutschsprachige CSV-Dateien können mit der Funktion `read.csv2()` importiert werden oder wir können die allgemeinere Funktion `read_delim()` nutzen und das Argument `delim = ";` hinzufügen. Damit nutzen wir das Semikolon als Separator.
Dies trifft zum Beispiel auf die Strukturdaten für die Wahlkreise zur Bundestagswahl 2021 zu. Die Bundeswahlleiterin stellt die Daten [hier](https://www.bundeswahlleiterin.de/bundestagswahlen/2021/strukturdaten.html) zur Verfügung. Versucht die Datei korrekt zu importieren. Ergänzt dafür das `delim = ";"` Argument.
```{r exercise_csv, exercise = TRUE}
# Ergänzt das `delim = ...` Argument:
strukturdaten <- readr::read_delim(
file = 'https://www.bundeswahlleiterin.de/dam/jcr/b1d3fc4f-17eb-455f-a01c-a0bf32135c5d/btw21_strukturdaten.csv', # Dateiname/Pfad zur Datei
col_names = TRUE, # Vorhandensein des Headers
skip = 8, # Wir müssen zudem 8 Zeilen überspringen. Am Besten öffnet Ihr die CSV-Datei einmal selbst mit einem Texteditor
na = c("", "NA") # Definition, wie "NA"-Werte aussehen z.B. "" (leer), festlegen
)
head(strukturdaten)
```
```{r exercise_csv-solution}
# Laden der Strukturdaten der Bundeswahlleiterin
strukturdaten <- readr::read_delim(
file = 'https://www.bundeswahlleiterin.de/dam/jcr/b1d3fc4f-17eb-455f-a01c-a0bf32135c5d/btw21_strukturdaten.csv', # Dateiname/Pfad zur Datei
delim = ";", # Wir legen das Semikolon als Separator fest
col_names = TRUE, # Vorhandensein des Headers
skip = 8, # Wir müssen zudem 8 Zeilen überspringen. Am Besten öffnet Ihr die CSV-Datei einmal selbst mit einem Texteditor
na = c("", "NA") # Definition, wie "NA"-Werte aussehen z.B. "" (leer), festlegen
)
head(strukturdaten)
```
```{r exercise_csv-check}
grade_this_code()
```
#### **XLSX**
Mit **Google Trends Daten** könnt Ihr erforschen, wonach die Welt gerade auf der Suchmaschine Google sucht. Das **Google Search Volume** (zu dt. Google Suchvolumen) bezieht sich dabei konkret auf die Anzahl der Suchanfragen, die Nutzer*innen zu einem bestimmten Suchbegriff innerhalb eines bestimmten Zeitraums eingeben. Ein hohes Volumen deutet auf hohes Interesse an einem Thema hin.
Wir haben für Euch zwei **XLSX-Dateien** erstellt, die zu den Suchbegriffen "beach clean up" (zu dt. Strand aufräumen), also Aktionen wie denen von "Break Free From Plastics", und "plastic pollution" (zu dt. Plastikverschmutzung) Daten enthalten. Das Arbeitsblatt "trends_over_time" stellt die Entwicklung des Google Search Volumes über die Zeit für die letzten fünf Jahre dar. "by_country" enthält die Entwicklung aufgeschlüsselt nach verschiedenen Ländern im Durchschnitt des letzten Jahres.
Hier laden wir mit der Funktion `readxl::read_excel()` das Arbeitsblatt (`sheet = ...`) "trends_over_time" der Excel-Datei "Plastic Pollution - Google Trends.xlsx" aus unserem Ordner "Daten" (`path = ...`), das Spaltenbezeichnungen enthält (`col_names = ...`) und in dem fehlende Werte zumeist durch "" (leer) gekennzeichnet sind (`na = ...`).
*Anmerkung: Zur Live-Verknüpfung mit den aktuellen Daten von Google gibt es in R das `gtrendsR`-Package. Dazu mehr in Exkurs 1.*
```{r exercise_xlsx, exercise = TRUE}
#install.packages(readxl)
# Laden der Entwicklung des Suchbegriffs "Plastic Pollution" über die Zeit
googletrendstime_plasticpollution <- readxl::read_excel(
path = here::here("daten/Plastic Pollution - Google Trends.xlsx"), # Definition von Path und Dateinamen
sheet = "trends_over_time", # Definition des Arbeitsblatts
col_names = TRUE, # Deklarierung der Spaltennamen
na = c("", NA)) # Syntax fehlender Werte
head(googletrendstime_plasticpollution)
```
Ladet nun das Arbeitsblatt "by_country" der Datei "Beach Clean Up - Google Trends.xlsx". Kopiert dazu den Code von oben und passt den Dateinamen und das Arbeitsblatt an der richtigen Stelle an.
```{r exercise_excel, exercise = TRUE}
# Euer Code hier
```
```{r exercise_excel-solution}
# Laden des Arbeitsblattes "by_country" der Datei "Beach Clean Up - Google Trends.xlsx"
readxl::read_excel(
path = here::here("daten/Beach Clean Up - Google Trends.xlsx"), # hier ändern wir den Dateinamen
sheet = "by_country", # hier ändern wir den Arbeitsblattnamen
col_names = TRUE,
na = c("", NA))
```
```{r exercise_excel-check}
grade_this_code()
```
### **Und jetzt Ihr**
Gerne könnt Ihr nun versuchen, **eigene Datensätze** in R zu importieren. Kommuniziert gerne über Slack, wenn Euch bestimmte Datensätze interessieren. Ansonsten (oder zusätzlich) gibt es die folgenden Aufgaben und das zugehörige **RMD 07_datenimport-uebung.Rmd** (im [Übungsordner](https://download-directory.github.io/?url=https://github.com/CorrelAid/lernplattform/tree/main/uebungen){target="_blank"} unter 07_datenimport):
1. Versucht, den "Plastics"-Datensatz (im Ordner `daten/plastics.csv` im [Übungsordner](https://download-directory.github.io/?url=https://github.com/CorrelAid/lernplattform/tree/main/uebungen){target="_blank"}) mit diesem Code **lokal zu laden**.
2. Ladet den "Plastics"-Datensatz über einen [**Hyperlink**](https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-01-26/plastics.csv){target="_blank"}.
3. *Bonus:* Mehr Strukturdaten vom Bundeswahlleiter: Wir wollen die Sturkturdaten der Bundestagswahl 2017 mit der Funktion *read_delim()* lokal laden. Die CSV-Datei könnt ihr [hier](https://www.bundeswahlleiterin.de/dam/jcr/f7566722-a528-4b18-bea3-ea419371e300/btw2017_strukturdaten.csv) herunterladen. Versucht die Datei manuell zu importieren. Achtet dabei auf den im Kapitel beschriebenen Ablauf: Öffnet die Datei mit einem Texteditor; welche Formatierung (encoding) hat sie? Dies könnt ihr beim manuellen Import unter "Locale" ändern. Die 2021er Strukturdaten lagen in der UTF-8 Kodierung vor. (Test: Was passiert, wenn wir die Locale nicht ändern?) Des Weiteren müsst ihr natürlich wieder auf die Argumente *skip* und *delim* achten.
### **Exkurse**
---
<details>
<summary><h4>➡ Exkurs 1: APIs</h4></summary>
<br>
<h2><b>Exkurs 1: APIs</b></h2>
<h3><b>APIs in R-Packages</b></h3>
Der Umgang mit APIs ist für Programmieranfänger*innen oft eine Herausforderung. Viele APIs sind aber bereits in passende **Packages** eingebettet, über die der Zugriff auf die Daten wesentlich leichter funktioniert. Über das Package `WDI` könnt Ihr beispielsweise **Daten der World Bank** laden, die Euch helfen können, Eure gesellschaftliche Herausforderung besser zu verstehen und zu kontextualisieren. In der Datenbank gibt es den Indikator "Terrestrial and marine protected areas (% of total territorial area)", der für die Planung von zukünftigen Aktivitäten und die Kommunikation mit Freiwilligen und Fördernden genutzt werden soll. Für "Break Free From Plastics" ist dieser Indikator spannend, weil in **Naturschutzgebieten** Flora und Fauna besser vor Plastikmüll geschützt sind. In Ländern, wo neben der hohen Müllmenge und der niedrigen Recyclingquoten, besonders wenige Gebiete als Naturschutzgebiete ausgezeichnet sind, könnte der Bedarf nach gemeinnützigen Organisationen wie "Break Free From Plastic", die die Natur von schädlichen Plastikmüll befreien, also besonders hoch sein.
*Anmerkung: Genau wissen wir das natürlich nicht, die Daten geben uns hier lediglich einen Hinweis darauf, wo der Bedarf groß sein könnte. Deshalb ist es wichtig die Annahmen, auf denen Entscheidungen basieren genau zu definieren und sich darüber Gedanken zu machen, ob die Datengrundlage für eine Entscheidung überhaupt ausreichend ist. Unsere Thesen können wir dann ggf. in Interviews mit Expert\*innen (hier z.B. Naturschützer\*innen) verifizieren.*
```{r wb, exercise = TRUE}
#install.packages("WDI")
# Daten der World Bank mit R-Package ziehen
wb_areas <- WDI::WDI(
country = "all", # Auswahl der Länder
indicator = "ER.PTD.TOTL.ZS", # Spezifikation des Indikators (Tipp: siehe Link in der Datenbank)
start = 2018, # Auswahl Zeithorizont: Anfang
end = 2018, # Auswahl Zeithorizont: Ende
language = "en" # Sprachauswahl
)
head(wb_areas)
```
Ladet nun den Datensatz zum Indikator ["Fish species, threatened" (EN.FSH.THRD.NO)](https://data.worldbank.org/indicator/EN.FSH.THRD.NO?view=chart){target="_blank"} für das Jahr 2018. Kopiert dazu den Code von oben und fügt den richtigen Indikatorschlüssel ein.
```{r exercise_wb, exercise = TRUE}
# Euer Code hier
```
```{r exercise_wb-solution}
# Daten der World Bank mit R-Package ziehen
WDI::WDI(
country = "all", # Auswahl der Länder
indicator = "EN.FSH.THRD.NO", # Spezifikation des Indikators (Tipp: siehe Link in der Datenbank)
start = 2018, # Auswahl Zeithorizont: Anfang
end = 2018, # Auswahl Zeithorizont: Ende
language = "en" # Sprachauswahl
)
```
```{r exercise_wb-check}
grade_this_code()
```
Daten mit APIs, die in R-Packages eingebettet sind, zu importieren, ist sehr einfach und wir sparen uns viel Zeit für die Datenbereinigung. Neben dem `WDI`-Package für die World Bank, gibt es noch viele **weitere, nützliche R-Packages**:
- `acled.api`-Package: Daten zu **bewaffneten Konflikten** von ACLED (zur [Doku](https://cran.r-project.org/web/packages/acled.api/index.html){target="_blank"}//mehr [Infos](https://acleddata.com/#/dashboard){target="_blank"})
- `datenguideR`-Package: Daten der **amtlichen Amtstatistik** in Deutschland (zum [Repo](https://github.com/CorrelAid/datenguideR){target="_blank"}//mehr [Infos](https://datengui.de/){target="_blank"})
- `DWD`-Package: Daten des **Deutschen Wetter Dienstes** (zur [Doku](https://github.com/CorrelAid/datenguideR){target="_blank"}//mehr [Infos](https://www.dwd.de/DE/Home/home_node.html){target="_blank"})
- `eurostat`-Package: Open Data von **Eurostat** (zur [Doku](https://cran.r-project.org/web/packages/eurostat/index.html){target="_blank"}//mehr [Infos](https://ec.europa.eu/eurostat/de/home){target="_blank"})
- `GermaParl`-Package: Plenarprotokolle des **Bundestags** (zur [Doku](https://cran.r-project.org/web/packages/gesisdata/index.html){target="_blank"}//mehr [Infos](https://www.gesis.org/home){target="_blank"})
- `gesisdata`-Package: Daten des **Leibniz-Instituts** (zur [Doku](https://cran.r-project.org/web/packages/gesisdata/index.html){target="_blank"}//mehr [Infos](https://www.gesis.org/home){target="_blank"})
- `googleAnalyticsR`-Package: Daten von **Google Analytics** (zur [Doku](https://cran.r-project.org/web/packages/googleAnalyticsR/index.html){target="_blank"}//mehr [Infos](https://analytics.google.com/analytics/web/provision/#/provision){target="_blank"})
- `gtrendsR`-Package: **Google Trends** Daten (zur [Doku](https://cran.r-project.org/web/packages/gtrendsR/gtrendsR.pdf){target="_blank"}//mehr [Infos](https://trends.google.com/trends/?geo=FR){target="_blank"})
- `nasadata`-Package: Daten von **NASA** (zur [Doku](https://cran.r-project.org/web/packages/nasadata/index.html){target="_blank"}//mehr [Infos](https://data.nasa.gov/){target="_blank"})
- `pangaear`-Package: Daten zu Erde und **Umwelt** (zur [Doku](https://cran.r-project.org/web/packages/pangaear/pangaear.pdf){target="_blank"}//mehr [Infos](https://www.pangaea.de/){target="_blank"})
- `rtweet`-Package: **Twitter**-Daten (zur [Doku](https://cran.r-project.org/web/packages/rtweet/rtweet.pdf){target="_blank"}//mehr [Infos](https://www.twitter.com/){target="_blank"})
- `salesforcer`-Package: Interaktion mit Daten in Salesforce (zur [Doku](https://cran.r-project.org/web/packages/salesforcer/index.html){target="_blank"})
- `dieZeit`-Package: Online-Veröffentlichungen der **Zeit** (zur [Doku](https://cran.r-project.org/web/packages/diezeit/index.html){target="_blank"}//mehr [Infos](https://www.zeit.de/){target="_blank"})
- uvm...
Schaut Euch gerne um - entweder über eine Suchmaschinenrecherche dazu, ob Eure Lieblingsdatenquelle ein zugehöriges R-Package hat, oder auf dieser Liste aller R-Packages, die über [CRAN](https://cran.r-project.org/web/packages/available_packages_by_name.html){target="_blank"} (Comprehensive R Archive Network, zu dt. Umfassendes R-Archivnetzwerk), die zentrale Stelle für geprüfte Package-Distribution, installiert werden können. <br>
*Hinweis: Manche Packages wurden (noch) nicht in die Liste der von RStudio geprüften CRAN-Packages aufgenommen. Ihre Installation erfolgt zumeist über den Befehl `remotes::install_github("Link zum Github-Repository")`.*
<h3><b>Eigene API Anfragen</b></h3>
[![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/deed.de)
*"Eigene API-Anfragen (Exkurs)" von Frie Preu in "R Lernen - der Datenkurs von und für die Zivilgesellschaft" von CorrelAid e.V. Lizensiert unter [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/deed.de).*
![*Video: Eigene API-Anfragen (10min)*](https://youtu.be/DePm6F_6YMA)
<h4><b>Interaktive Übung</b></h4>
Eine API (_Application Programming Interface_, de: Schnittstelle zur Programmierung von Anwendungen) ist eine Schnittstelle, die ein System bereitstellt, um anderen Programmen die Interaktion zu ermöglichen.
Eine Interaktion sieht so aus:
1. Der **Client** macht eine Anfrage (engl. Request) an die API
2. Die API verarbeitet die Anfrage und gibt eine Antwort (engl.: **Response**) zurück.
3. Der Client verarbeitet die Antwort.
APIs verfügen zumeist über eine **Dokumentation**, die enthält, welche Funktionalitäten verfügbar sind und wie Anfragen gestellt werden müssen.
**Analogie**: Wenn Ihr (als _Client_) im Restaurant seid, stellt Euch das Restaurant eine*n Kellner\*in (Eure _API_) und eine Speisekarte (Eure _API-Dokumentation_) bereit. Der\*die Kellner\*in nimmt Eure Bestellungen (_Anfragen_) entgegen, die Küche verarbeitet diese und der:die Kellner\*in bringt Eure Bestellung (_Antwort_).
Die allermeisten APIs heutzutage verwenden das HTTP-Protokoll, welches fünf sogenannte _Methoden_ umfasst: GET, POST, PUT, PATCH und DELETE. Da wir in unserem Fall auf Interaktionen schauen, welche sich auf den Datenaustausch fokussieren, ergeben sich folgende Entsprechungen:
- `GET` --> Daten lesen
- `POST` --> Neue Daten erstellen
- `PUT` --> Daten ersetzen
- `PATCH` --> Daten aktualisieren
- `DELETE` --> Daten löschen
(siehe Folie 10 von ["Datenzugriff im World Wide Web"](https://projektzyklus.correlaid.org/07_datenmanagement-webdaten/2021-05-09_Datenzugriff_im_WWW.pdf), Jan Dix, lizensiert unter [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/legalcode.de).)
[Hier (en)](https://github.com/public-apis/public-apis) findet Ihr eine Liste von öffentlichen APIs, die Ihr kostenfrei nutzen könnt.
<h4><b>GET-Anfragen</b></h4>
Wenn Ihr nur Daten laden möchtet, reicht `GET` meistens aus. Je nach API können allerdings auch `POST` Anfragen notwendig sein. `GET`-Anfragen können als normale URL (das was Ihr in euren Browser eingebt) abgebildet werden. Diese URLs setzen sich aus drei Teilen zusammen:
`{BASIS_URL}/{ROUTE}?{QUERY_PARAMETER}`.
Das kennt Ihr zum Beispiel von einer Google-Suche: `https://www.google.com/search?q=CorrelAid`.
- `BASIS_URL`: `https://www.google.com/`
- `ROUTE`: `search`
- `QUERY_PARAMETER`:
- `q`: `CorrelAid`
**Analogie**: Im Restaurant bestellt (--> `GET`) Ihr bei Elmo (Eure API mit der Basis-URL `https://elmo.correlandfriends.de/`) auf der Route "Essen" (`essen`) das Gericht Risotto (Query-Parameter `gericht=risotto`). Die komplette Anfrage-URL wäre also: `https://elmo.correlandfriends.de/essen?gericht=risotto`. Das Fragezeichen signalisiert das Ende der Route und den Anfang der Query-Parameter.
<h4><b>Statuscodes</b></h4>
Fast alle APIs geben in Ihrer Antwort einen Code zurück, anhand dem man schnell sehen kann, ob die Anfrage erfolgreich war oder nicht. Dieser sogenannte _Statuscode_ ist sehr hilfreich, da er Aufschluss gibt, was schief gegangen sein könnte.
Wenn die Anfrage erfolgreich war, gibt die API einen `200` Statuscode zurück. Darüber hinaus gibt es viele Statuscodes, die einen Fehler anzeigen. Häufige Fälle sind:
- `404`: Nicht gefunden ("Not found"). Z.B. existiert der Endpunkt / die Route gar nicht in der API
- `401`: Nicht autorisiert ("Not authorised"): Ihr seid nicht autorisiert auf die API zuzugreifen, z.B. weil Ihr keinen *Token* übergeben habt.
- `403`: Nicht erlaubt ("Forbidden"): Ihr seid zwar im Prinzip für die API autorisiert, aber nicht für die Route, auf die ihr zugreifen wollt (z.B. sensitive Daten oder Administration).
- `422`: Nicht verarbeitbare Anfrage ("Unprocessable Entity"): Eure Anfrage wurde nicht richtig gestellt
- `500`: Interner Server-Fehler ("Internal Server Error"): Eure Anfrage ist zwar richtig gestellt worden, innerhalb der API kam es aber zu einem Fehler
**Analogie**: Nach Eurem Besuch im Restaurant "Correl and Friends" geht Ihr noch in die Bar "AidBar". Doch irgendwie seid Ihr nicht so richtig satt geworden vorhin und bestellt, ohne die Karte (_API -Dokumentation_) zu konsultieren, eine Pommes (`/essen?gericht=Pommes`). Leider muss Euch die Kellnerin enttäuschen, "Aid's Tavern" verkauft nur Getränke: 404!
Auf Folien 13-16 [dieses Foliensatzes](https://projektzyklus.correlaid.org/07_datenmanagement-webdaten/2021-05-09_Datenzugriff_im_WWW.pdf) findet Ihr noch mehr Erklärungen zu wichtigen Statuscodes.
<h4><b>Beispiel</b></h4>
Wir verwenden die [Sustainable Development Goals (SDG) API](https://unstats-undesa.opendata.arcgis.com/#api) der Vereinten Nationen (en: _United Nations_), welche Daten über den Fortschritt der [Sustainable Development Goals](https://sdgs.un.org/) bereitstellt. Die Dokumentation der API findet Ihr [hier](https://unstats.un.org/SDGAPI/swagger/). Der Indikator "[Municipal Solid Waste collection coverage by cities (percent)](https://www.sdg.org/datasets/undesa::indicator-11-6-1-municipal-solid-waste-collection-coverage-by-cities-percent/about)" (Seriencode: `EN_REF_WASCOL`) passt gut zu unseren bisherigen Analysen zum Thema Plastikverschmutzung. Um die Daten zu diesem Indikator zu laden, verwendet Ihr den GET-Endpunkt [`/v1/sdg/Series/Data`](https://unstats.un.org/SDGAPI/swagger/#!/Series/V1SdgSeriesDataGet). Zudem habt Ihr nun mehrere Möglichkeiten, Query-Parameter anzugeben, unter anderem den Code des Indikators (`seriesCode`) und den Zeitrahmen, für den Ihr Daten benötigt.
Um Anfragen an APIs zu machen, nutzen wir das [`httr`](https://httr.r-lib.org/)-Package (Doku).
```{r series-req, exercise=TRUE}
# library(httr)
basis_url <- "https://unstats.un.org/" # Haupt-URL
initiale_anfrage <- httr::GET( # Initialisierung
basis_url, # URL verlinken
path = "/SDGAPI/v1/sdg/Series/Data", # Route definieren
query = list(
seriescode = "EN_REF_WASCOL"
)
)
```
Wenn wir uns die Anfrage-URL anschauen, erkennen wir wieder das Schema `{BASIS_URL}/{ROUTE}?{QUERY_PARAMETER}`.
```{r waste-url, exercise=TRUE}
initiale_anfrage$url
```
```{r quiz-route, exercise = FALSE, echo=FALSE}
quiz(caption = NULL,
question("Was ist die Basis-URL der Anfrage?",
answer("https://unstats.un.org/SDGAPI/v1/sdg/Series/Data"),
answer("https://unstats.un.org/SDGAPI/v1/sdg/Series/"),
answer("https://unstats.un.org/", correct = TRUE),
correct = "Richtig!",
incorrect = "Leider falsch: Schaue dir den Code nochmal an!",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"),
question("Was ist die Route der Anfrage?",
answer("v1/sdg/Series/Data"),
answer("SDGAPI/v1/sdg/Series/Data/", correct = TRUE),
answer("sdg/Series/"),
correct = "Richtig!",
incorrect = "Leider falsch: Schaue dir den Code nochmal an!",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("Wie viele Parameter hat unsere Anfrage?",
answer("0"),
answer("1", correct = TRUE),
answer("2"),
answer("3"),
answer("4"),
correct = "Richtig!",
incorrect = "Leider falsch: Schaue dir den Code nochmal an!",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
)
)
```
Zuerst checken wir nun den **Statuscode**, um sicher zu gehen, dass unsere Anfrage erfolgreich war. In `httr` gibt es hierzu auch die `stop_for_status` Funktion, die einen Fehler schmeißt, wenn die Anfrage nicht erfolgreich war, sonst aber nichts tut.
```{r waste-status, exercise=TRUE}
initiale_anfrage$status_code # 200
httr::stop_for_status(initiale_anfrage) # nichts passiert, alles gut!
```
Nun fragen wir uns: **Wie viele Seiten Dokument** müssen überhaupt geladen werden? APIs geben Euch nämlich meistens nicht von Haus aus alle Resultate zurück.
```{r apicontent, exercise = TRUE}
# Vorläufig Inhalt der Inititalabfrage zur Prüfung speichern
content <- httr::content(initiale_anfrage)
# Einlesen der Seitenanzahl durch das Attribut "totalPages", auf das wir mithilfe von "$" zugreifen
total_pages <- content$totalPages
print(total_pages)
pages <- c(1:total_pages)
```
Diese Information merken wir uns und schauen uns nun an, was genau die Antwort unserer Anfrage beinhaltet. Diese erhaltet Ihr, indem Ihr die Funktion `httr::content()` (de: Inhalt) verwendet. Output dieser Funktion ist eine **vielschichtige (eng. nested) Liste**.
```{r content, exercise=TRUE}
# Inhalt der Response herausziehen
httr::content(initiale_anfrage)
```
Wir erhalten von der Anfrage also eine Liste mit mehreren Elementen zurück, die die gesamte _Antwort_ darstellt. Als Anwender:innen seid Ihr hauptsächlich an den **übermittelten Daten** interessiert, die wir nun ziehen ("$data") . Mit `purrr::map_df` können wir nun die Datenliste (ebenfalls vielschichtig) entpacken.
```{r goals-extract, exercise=TRUE}
# Für verschiedene Städte in verschiedenen Ländern erhalten wir so zu verschiedenen Jahren Ihre Müllsammlungsquoten
waste_list <- waste_data$data
# Mit dem purrr-Package ziehen wir nun die Daten in einen Dataframe
library(purrr)
waste_geo <- waste_list %>%
purrr::map_df(`[`, c("geoAreaCode", "geoAreaName", "dimensions", "value")) %>%
filter(dimensions != "G") # Duplikate entfernen, die aus der Datenstruktur resultieren
# Datensatz betrachten
dplyr::glimpse(waste_geo)
```
Abschließend schauen wir uns nochmal genauer eines der Datenelemente an:
```{r inspect-data, exercise=TRUE}
# Wir schauen uns eines der Daten Elemente an. Die doppelten Klammern extrahieren das x-te Element aus der Liste, hier das zehnte.
str(waste_data$data[[10]])
```
Das Daten-Listenelement enthält ziemlich viele Informationen. Für Euch relevant ist der Wert (`value`) sowie die Informationen über das "Wo": `geoAreaCode` und `geoAreaName`.
Diese Informationen nutzen wir nun - gemeinsam mit der Seitenanzahl - um für jede Seite die benötigten Informationen zu ziehen und diese in einem Dataframe zusammenzuführen. Wie genau Ihr mit solchen komplexeren Datenstrukturen umgehen könnt und diese Daten aus _allen_ Elementen extrahieren könnt, lernt Ihr zu einem späteren Zeitpunkt in Eurer Karriere als Datenwissenschaftler\*innen der Zivilgesellschaft - hier schon einmal die Preview:
```{r listofdataframes, exercise=TRUE}
# Funktion, mit der alle Seiten geladen werden, indem die Seitenanzahl "Page" durch eine Nummer zwischen 1 und 11 (= Total Pages) ersetzt wir
list_of_dataframes <- purrr::map(pages, function(page) {
antwort <- httr::GET(
basis_url,
path = "/SDGAPI/v1/sdg/Series/Data",
query = list(
seriescode = "EN_REF_WASCOL",
page = page # Hier wird die Seitenzahl eingesetzt
)
)
# Von jeder Seite die Daten laden
waste_list <- httr::content(antwort)$data
# Generierung eines Dataframes mit den ausgewählten Variablen
waste_geo <- waste_list %>%
purrr::map_df(`[`, c("geoAreaCode", "geoAreaName", "dimensions", "value"))
return(waste_geo)
})
# Erstellung eines großen Dataframes mit allen Daten
waste_geo_df <- dplyr::bind_rows(list_of_dataframes)
```
<h4><b>Authentifizierung</b></h4>
In unserem Beispiel konnten wir ohne Authentifizierung die UN-SDG API verwenden. Die meisten APIs erfordern allerdings eine Authentifizierung, d.h. Ihr müsst beweisen, dass Ihr berechtigt (*autorisiert*) seid, auf die API und ihre Daten zuzugreifen.
Hierzu gibt es viele verschiedene Modelle. Im einfachsten Fall erstellt ihr euch einen sogenannten Token in der entsprechenden Website in den Benutzereinstellungen. Ein **Token** ist ein zufällig erstellter String, quasi euer API-"Passwort". Tokens sehen meistens so aus `eyJpc3MiOiJodHRwczovL2V4YW1...`.
```{r authorization-ex, exercise=FALSE, eval=FALSE, echo=TRUE}
# Liest die Umgebungsvariable API_TOKEN und speichert sie im Objekt Token
basis_url <- "https://beispielapi.org/"
token <- Sys.getenv("API_TOKEN")
# Füge unserer Anfrage einen Autorisierungs-Header hinzu, sodass die API weiß, dass wir autorisiert sind
antwort <- httr::GET(basis_url,
httr::add_headers(Authorization = paste("Authorization", token)))
```
Die Details zur Authentifizierung sind von API zu API unterschiedlich. Die genauen Instruktionen solltet ihr in der jeweiligen API-Dokumentation finden.
Es gibt spezifische Statuscodes, die in Verbindung mit Authentifizierung besonders häufig auftauchen: 401 und 403. Diese Fehlercodes tauchen häufig auf, wenn man eigentlich den richtigen Token hat, aber ihn in der Anfrage nicht richtig übergeben hat. Lest deshalb immer genau in der Dokumentation nach, wie die Authentifizierung der API im Detail funktioniert.
Aus Sicherheitsgründen ist es zudem sehr wichtig, Euren Token (oder sonstige **sicherheitsrelevante Informationen**) **nicht direkt im Code zu speichern**. Anstatt dessen nutzt ihr hierzu am besten **Umgebungsvariablen** (engl. environment variables). Wie man Umgebungsvariablen zu R hinzufügt, ist in [diesem Blogpost](https://www.roelpeters.be/what-is-the-renviron-file/) gut beschrieben. Auch wir üben das zu einem späteren Zeitpunkt nochmal.
<h3><b>Zusätzliche Ressourcen</b></h3>
- Ihr wollt mehr darüber lernen, wie man API-Anfragen selbst schreibt? Dataquest bietet den Kurs ["APIs in R"](https://app.dataquest.io/course/apis-in-r){target="_blank"} (engl.) an.
</details>
---
---
<details>
<summary><h4>➡ Exkurs 2: Geo(-referenzierte) Daten</h4></summary>
<br>
<h2><b>Exkurs 2: Geo(-referenzierte) Daten</b></h2>
[![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/deed.de)
*"Geo(-referenzierte) Daten (Exkurs)" von David Schweizer in "R Lernen - der Datenkurs von und für die Zivilgesellschaft" von CorrelAid e.V. Lizensiert unter [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/deed.de).*
Um Karten zu erstellen, nutzt Ihr verschiedene geometrische Typen und müsst Eure Datensätze somit um unterschiedliche geographische Daten ergänzen (sog. Geocodierung). Bei der Darstellung von Punkten auf der Karte benötigt Ihr **Längen- und Breitengrad** der Orte, die Ihr visualisieren möchtet. Für eindimensionale Linien (z.B. Straßen) benötigt Ihr eine **Reihe an Punkten** mit dem jeweiligen Längen- und Breitengrad. Zweidimensionale Kartenbereiche werden mit Polygonen geocodiert. **Polygone** stellen kartographische Informationen dar - beispielsweise die Form und Lage von Deutschland auf einer Weltkarte. Diese Daten lesen wir mit dem Package `sf` und der Funktion `st_read()` ein. <br>
*Achtung: Damit der Import funktioniert müsst Ihr die gesamte ZIP-Datei, die Ihr laden wollt, in einem Ordner mit der hier gewünschten .shp-Datei ablegen - also auch alle Dateien mit anderen Endungen.*
```{r polygons_world, exercise = TRUE}
# install.packages("sf")
# Einlesen des globalen Shapefiles (geometrischen Datensatzes, erkennbar an .shp) über sf::st_read()
polygons_welt <- sf::st_read(here::here("daten/geospatial/ne_50m_admin_0_countries.shp"))
```
Unser Datensatz enthält zahlreiche Spalten mit zusätzlichen Informationen zu den Ländern der Welt. Uns interessiert hier die Spalte "`geometry`", die die kartographischen Informationen enthält.
```{r polygon_welt_exercise, exercise = TRUE}
# Betrachtung der Daten
head(polygons_welt$geometry)
```
Zur Veranschaulichung können wir nun die Polygone des Datensatzes `polygons_welt` veranschaulichen. Wir nutzen hier die `baseR`-Funktion `plot()`. Wie wir mit kartographischen Daten schönere und insb. interaktive Karten gestalten, lernt Ihr in Lektion 11 - Datenvisualisierung.
```{r polygon_welt__plot_exercise, exercise = TRUE}
# Erstellung eines einfachen Kartenplots
plot(polygons_welt$geometry)
```
Auch für Deutschland gibt es ähnliche Shapefiles:
```{r polygon_de_exercise, exercise = TRUE}
# Einlesen der Deutschlandkarte mit Bundesländern
polygons_deutschland <- sf::st_read(here::here("daten/geospatial/1000_NUTS1.shp"))
plot(polygons_deutschland$geometry)
```
Der Import von geographischen Daten folgt also der folgenden Checkliste:
1. Welche **geographische Ebene** soll visualisiert werden (Punkte, Striche oder Polygone)?
2. Wo kann ich zugehörige **Shapefiles** finden? <br>
*Tipp: [Hier](http://www.naturalearthdata.com/features/){target="_blank"} findet Ihr globale und beim [Bundesamt für Kartographie](https://gdz.bkg.bund.de/index.php/default/nuts-gebiete-1-1-000-000-stand-31-12-nuts1000-31-12.html){target="_blank"} deutsche Shapefiles. Einige können auch über Packages und Links geladen werden.*
3. Über welche **Schlüsselvariable** füge ich meinen Datensatz und die geographischen Daten zusammen? Gibt es (sprachliche) Hürden (Deutschland != Germany != DEU)?
</details>
---
---
<details>
<summary><h4>➡ Exkurs 3: Datenabfragen in SQL</h4></summary>
<br>
<h2><b>Exkurs 3: Datenabfragen in SQL</b></h2>
[![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/deed.de)
*"Datenabfragen in SQL" von Nina Hauser in "R Lernen - der Datenkurs von und für die Zivilgesellschaft" von CorrelAid e.V. Lizensiert unter [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/deed.de).*
<h3><b>Interaktive Übung</b></h3>
Daten, die uns in unserem Alltag als Datenanalyst\*innen und Datenwissenschaftler\*innen begegnen, sind oft in **Datenbanken** gespeichert. Datenbanken sind **logisch modellierte, strukturierte Datenspeicher**, mit denen mit Hilfe von **Datenbankmanagementsystemen (kurz DBMS)**, also Softwaretools, interagiert werden kann. Diese Interaktion funktioniert für jedes Datenbankmanagementsystem anders und ist **nicht trivial**. Während in einigen Fällen ein manueller Export als XLSX-, CSV- oder JSON-Datei möglich ist, kann es in einigen Fällen, auch auf Grund der Größe der Datensätze, nicht praktikabel sein manuell Daten zu exportieren. Daneben ist das natürlich auch IT im Schneckentempo statt in Lichtgeschwindigkeit. Idealerweise sind Eure Daten nämlich **live** mit Euren Analysetools verknüpft, sodass sie beständig aktuell sind. Die populärsten Datenbankmanagementsysteme findet Ihr in dieser Übersicht einer Umfrage unter Entwickler:innen von [Stack Overflow](https://insights.stackoverflow.com/survey/2020#technology-databases-all-respondents4){target="_blank}.
<center>
![*2020 Developer Survey, Stack Overflow, n = 65,000*](https://github.com/CorrelAid/lernplattform/blob/main/abbildungen/05_datenimport/popular_dbms.png?raw=true){#id .class width=50% height=50%}
</center>
An einer Technologie kommt man beim Thema Datenbanken also nicht vorbei: **SQL (Structured Query Language, zu dt. Strukturierte Abfragesprache)**. SQL erlaubtuns aus SQL-basierten Datenbanken Daten abzufragen. Wie bei R handelt es sich hier also um eine Programmiersprache mit eigenem Syntax. Um erste Abfragen zu generieren, reichen allerdings nur wenige Befehle aus. In diesem Code Chunk stellen wir die Verbindung zu einer SQLite-DBMS her (Platz 4 in der 2020 Developer Survey von Stack Overflow).
```{r exercise_sqlite, exercise = TRUE, message = FALSE}
# Laden der benötigten Packages für die Verknüpfung mit SQLite-Datenbanken
library(RSQLite)
library(DBI)
# Initialisierung eines temporären Ordners
tmpfile <- tempfile(fileext = "sqlite") # Identifizierung der SQLite-DB über das Suffix "sqlite"
download.file("https://correlaid.github.io/lernplattform/daten/plastics.sqlite", tmpfile) # Herunterladen der temporären Datei
con <- dbConnect(RSQLite::SQLite(), tmpfile) # Aufbau der Verbindung
```
Die Live-Verknüpfung selbst funktioniert wie erklärt **für jede Datenbank anders** - dieser Code kann also nicht einfach übertragen werden. Für einen Großteil der verschiedenen DBMS und zugehörige Importmöglichkeiten gibt es jedoch von RStudio eine praktische [Übersicht](https://db.rstudio.com/tooling/pro-drivers/){target="_blank"}. Ist Euer Analysetool mit der Datenbank verknüft, könnt Ihr in der zugehörigen Abfragesprache **Abfragen** generieren. Schauen wir uns dazu zunächst an, wie das ERM (Entity-Relationship-Modell, zu dt. Datenbankschema) der Datenbank aussieht:
![*ERM der Plastics-SQLite-Datenbank*](https://github.com/CorrelAid/lernplattform/blob/main/abbildungen/05_datenimport/erm.png?raw=true){#id .class width=50% height=50%}
```{r quiz_dbdiagramm}
quiz(
caption = "Was fällt Euch auf?",
question_numeric(
"Wie viele Tabellen enthält das Datenbankschema?",
answer(3, correct = TRUE),
correct = "Richtig! Bei den Tabellen Audit Plastic und Community handelt es sich um Entitäten, also identifizierbare Objekte, während in der Tabelle Countries lediglich eine Beziehung zwischen den beiden Entitätstabellen hergestellt wird. Alle Tabellen haben Attribute (Eigenschaften).",
incorrect = "Leider falsch. Es gibt drei Tabellen. Bei den Tabellen Audit Plastic und Community handelt es sich um Entitäten, also identifizierbare Objekte, während in der Tabelle Countries lediglich eine Beziehung zwischen den beiden Entitätstabellen hergestellt wird. Alle Tabellen haben Attribute (Eigenschaften).",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question(
"Anhand welchen Attributs werden die Tabellen verknüpft?",
answer("year"),
answer("plastics"),
answer("countrycode", correct = TRUE),
correct = "Richtig! Das erkennt man daran, dass dieses Attribut in allen drei Tabellen auftaucht.",
incorrect = "Leider falsch. Das erkennt man an dem Attribut countrycode, das in allen drei Tabellen auftaucht." ,
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
)
)
```
In einer **idealen Welt** würde so auch unser Datensatz aussehen - aufgeteilt nach Entitäten (identifizierbare Objekte) und ihren jeweiligen Attributen (Eigenschaften) in drei klar benannten Tabellen, in der jede Zeile für eine Beobachtung steht. In der realen Welt passiert das allerdings selten. So ist es eben. Wichtig ist, dass Ihr auch mit solchen Daten arbeiten könnt, aber versteht, dass Eure Datenbanken idealerweise dieser Grundlogik folgen.
Für **SQL-basierte Datenbanken** werden Abfragen nun in der zugehörigen Abfragesprache SQL erstellt. Mit `dbListTables(Verbindung)` könnt Ihr Euch die Tabelle, die das DBMS enthält **anzeigen** lassen. Mit `dbReadTable(Verbindung, Tabelle)` könnt Ihr die gewünschte **Gesamttabelle laden** und als Objekt in R **speichern**. Mit `dbGetQuery(Verbindung, "SQL Befehl")` könnt Ihr die Tabelle filtern und so **Teilmengen des Datensatzes laden** (und ggf. in R als Objekt speichern).
```{r exercise_queries, exercise = TRUE}
# Abfrage der Tabellen
dbListTables(con)
# Speicherung der Tabelle "Audit Plastic" als Objekt
audit_plastic <- dbReadTable(con, "audits")
# Laden eines gefilterten Datensatzes (Land = Benin)
dbGetQuery(con, "SELECT *
FROM audits
WHERE countrycode = 'BEN'") # Achtung: Während wir R Ist-gleich-Vergleiche mit "==" initialisieren, benutzt man in SQL nur ein "="
# Laden eines gefilterten Datensatzes (Hersteller = Nice And Lovely)
dbGetQuery(con, "SELECT *
FROM audits
WHERE parent_company = 'Nice And Lovely'")
```
Die wichtigsten **Befehle zur Datenabfrage in SQL** sind:
- `SELECT`: **Auswahl** aller **Spalten** (mit *) oder definierter Spalten
- `FROM`: **Auswahl** eines **Datensatzes**
- `WHERE`: **Filtern des Datensatzes** auf Basis von Kriterien
Versucht hier die Datentabelle "events" für Australien zu filtern.
```{r exercise_sql, exercise = TRUE}
# Euer Code hier
```
```{r exercise_sql-solution}
# Laden eines gefilterten Datensatzes (Land = AUS)
dbGetQuery(con, "SELECT *
FROM events
WHERE countrycode = 'AUS'")
```
```{r exercise_sql-check}
grade_this_code()
```
Im letzten Schritt **schließen** wir **immer** die **Verbindung** zu der Datenbank mit dem Befehl `dbDisconnect()`.
```{r dbclose_exercise, exercise = TRUE}
# Schließen der DB-Verbindung
dbDisconnect(con)
```
SQLite-Datenbanken benötigen in der Regel **kein Passwort** (und somit auch keinen Code für die Authentifizierung). Falls das für Euch notwendig ist, findet Ihr in der Dokumentation von RStudio in den Kapiteln [Database](https://docs.rstudio.com/connect/1.7.8/admin/database-provider.html){target="_blank"} und [Authentication](https://docs.rstudio.com/connect/1.7.8/admin/authentication.html){target="_blank"} Hilfestellungen.
<h3><b>Zusätzliche Ressourcen</b></h3>
Ihr wollt mehr SQL lernen? Dataquest bietet den Kurs [SQL Fundamentals](https://app.dataquest.io/course/sql-fundamentals){target="_blank"} und [Intermediate SQL in R](https://app.dataquest.io/course/sql-intermediate-r){target="_blank"} auf DataQuest (engl.)
</details>
---
### **Zusätzliche Ressourcen**
- [Cheat Sheet: Data import](https://github.com/CorrelAid/lernplattform/blob/main/cheatsheets/05_cheatsheet-import.pdf){target="_blank"} (engl.)
- [Web Scraping in R](https://app.dataquest.io/course/scraping-in-r){target="_blank"} auf DataQuest (engl.)