-
Notifications
You must be signed in to change notification settings - Fork 2
/
11_0_exkurs-automatisierte-reports.Rmd
418 lines (306 loc) · 26.7 KB
/
11_0_exkurs-automatisierte-reports.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
---
title: "Exkurs: Reportautomatisierung"
author: CorrelAid e.V.
date: "`r Sys.Date()`"
authors:
- Lisa Reiber
- Jonas Lorenz
output:
html_document:
toc: true
toc_depth: 2
toc_float: true
theme: flatly
css: www/style.css
includes:
after_body: ./www/favicon.html
language: de
runtime: shiny_prerendered
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
library(learnr)
library(gradethis)
library(dplyr)
source("R/setup/gradethis-setup.R")
source("R/setup/tutorial-setup.R")
# Read app parameters
params <- yaml::yaml.load_file("www/app_parameters.yml")
# Benötigte Daten laden
source("R/setup/functions.R")
audit <- get_audit()
params <- get_params()
```
```{r results='asis'}
cat(get_license_note(rmarkdown::metadata$title, rmarkdown::metadata$authors))
```
# **Reportautomatisierung mit R Markdown**
![*Video: Reportautomatisierung (20min)*](https://youtu.be/78r2ugQ6bdQ)
## **Kernaussagen**
- Berichte in R Markdown anzulegen, bedeutet, **reproduzierbare Reports** zu erstellen.
- So können...
a) Reports leicht **aktualisiert**,
b) **verschiedene Layoutformate** gleichzeitig und
c) **eine hohe Anzahl** von Berichten pro **Ausprägung einer Entität** (z.B. Länder und Zeiträume) erstellt werden.
- In dieser **Flexibilität** von R Markdowns liegt auch ihr Mehrwert.
- Technisch ist dafür zumeist das Verwenden von **Parametern** (zu dt. Übergabewerte) notwendig.
---
## **Das `rmarkdown`-Package**
<right>
![*ggplot2](https://pkgs.rstudio.com/rmarkdown/reference/figures/logo.png){#id .class width=20% height=60%}
</right>
<br>
Bei der technischen Umsetzung automatisierter Reports greifen wir auf das Package **`rmarkdown`** zurück. Das Package bietet verschiedene Funktionen zur Erstellung dynamischer und **reproduzierbarer Dokumente** in verschiedenen Ausgabeformaten wie HTML, PDF, Word, Präsentationen und sogar interaktiven Dashboards. Zu den wichtigsten Funktionen des R Markdown-Packages gehört die Möglichkeit, **Parameter festzulegen**, welche das Dokument besonders flexibel machen. Was genau sich dahinter verbirgt und welche Paramter wir verändern können bzw. müssen, schauen wir uns jetzt einmal im Detail an!
---
## **Parameter in R Markdown**
(Meta-) Parameter sind Variablen, die in Computerprogrammen **verschiedene Ausprägungen** annehmen können und für die Art und Weise der **Verarbeitung** von Informationen in Routinen relevant sind (z.B. wenn individuelle Reports für verschiedene Beobachtungen erstellt werden). Diese Parameter werden im **YAML-Abschnitt** von R Markdown-Dokumenten definiert. Wir können dabei Parameter der folgenden **Typen** festlegen:
- `character`: Ein character-Parameter wird für **Textwerte** genutzt, wie Namen, Titel oder Kategorien. Sie sind praktisch, um Textausgaben dynamisch zu gestalten oder bestimmte Namen und Titel im Report zu aktualisieren
- `integer`: Der integer-Parameter repräsentiert **ganze Zahlen** (z.B. 1, 2, 3 oder -10). Dieser Typ ist nützlich für Zählwerte, die dargestellt werden müssen, z.B. zur Auswahl eines spezifischen Jahres oder zur Angabe einer Anzahl.
- `numeric`: numeric-Parameter erfassen **allgemeine Zahlen**, einschließlich Dezimalzahlen. Sie eignen sich für Berechnungen, Messungen oder andere numerische Eingaben, die Präzision oder genaue Berechnungen erfordern.
- `logical`: Der logical-Parameter (logischer Ausdruck) ist ein binärer TRUE/FAlSE-Wert, um **Bedingungen** festzulegen, die bestimmte Abschnitte im Dokument ein- oder auszublenden (z.B. eine bestimmte Visualisierung oder Tabelle).
- Ausdrücke in R: Man kann auch komplexere Parameter wie **R-Ausdrücke** verwenden. Das können vordefinierte Berechnungen sein, die als Startwert genutzt werden (z.B. eine Funktion oder Berechnung, die für den Report spezifisch ist).
Die Anpassung der Parameter kann im YAML-Abschnitt selbst oder innerhalb der **Renderfunktion** `rmarkdown::render("MyDocument.Rmd", params = ...)` erfolgen. Bei Bedarf ist die Auswahl allerdings auch über **interaktive Menüs** möglich: (**Menü-Option** `Knit -> Knit with parameters` oder `rmarkdown::render(input = ..., params = "ask")`). Innerhalb des R Markdowns kann auf die selbst benannten Parameter über `params$parameter_name` **zugegriffen** werden
---
## **Quiz**
```{r 11quiz_reportauto}
quiz(caption = NULL,
question("R Markdowns sind reproduzierbar. Das hat den Vorteil, dass...",
answer("... sie leicht aktualisiert werden können.", correct = TRUE),
answer("... sie in verschiede Layoutformate übertragen werden können.", correct = TRUE),
answer("... sie für verschiedene Szenarien erstellt werden können.", correct = TRUE),
answer("... sie problemlos auf völlig andere Daten übertragen werden können."),
correct = "Richtig, die Reproduzierbarkeit von R Markdown-Dokumenten bedeutet, dass sie mühelos aktualisiert und für unterschiedliche Layouts oder ähnliche Datensätze verwendet werden können! Dadurch eignen sie sich gut für automatisierte Berichte oder regelmäßige Analysen mit aktualisierten Daten.",
incorrect = "Leider falsch, die im Code verwendeten Operationen sind meist auf die Struktur des Datensatzes abgestimmt. Daher ist es unwahrscheinlich, dass der gleiche Code ohne Anpassungen auf völlig unterschiedliche Daten anwendbar ist. Die Datenstruktur sollte konsistent sein, insbesondere wenn Ihr den Bericht parametrisieren wollt.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("Der Mehrwert von R Markdowns liegt in...",
answer("... der leichten Anpassungsfähigkeit ihrer Designs."),
answer("... ihrer Reproduzierbarkeit.", correct = TRUE),
answer("... ihrem niedrigschwelligen User Interface für nicht so tech-affine Nutzer:innen."),
correct = "Richtig, glücklicherweise gibt es tolle Layouttemplates und die Möglichkeit der interaktiven Parametrisierung durch GUIs, die es uns vereinfachen, Reports anschaulich und nutzerinnenfreundlich zu gestalten. GUIs steht für 'Graphical User Interfaces' (zu dt. grafische Benutzeroberflächen).",
incorrect = "Leider falsch, das Layout von R Markdowns muss oft in HTML und CSS codiert werden. Deshalb nutzen wir in der Regel Templates. Teilen wir außerdem R Markdowns direkt (also nicht das Outputformat) ist auch die Nutzung in RStudio gar nicht so leicht - wie Ihr ja bereits wisst. Da müssen wir also Zeit in das Set-up und die gute Erklärung des Tools stecken.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("Parameter sind...",
answer("... Platzhalter, die es ermöglichen einen Wert einmal zu definieren, und ihn an verschiedenen Stellen im Code zu übergeben.", correct = TRUE),
answer("... eine Maßeinheit der Performance in der Computerwissenschaft."),
correct = "Richtig, glücklicherweise müssen wir in der Computerwissenschaft keine 100 Parameter-Sprints laufen!",
incorrect = "Leider falsch, glücklicherweise müssen wir in der Computerwissenschaft keine 100 Parameter-Sprints laufen!",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("Wie können Parameter gesetzt und übergeben werden?",
answer("Über den YAML-Header, optional: Mit GUI", correct = TRUE),
answer("In einer beliebigen Stelle im Code"),
answer("Über die Render-Funktion, optional: Mit GUI", correct = TRUE),
correct = "Richtig, Parameter können über den YAML-Header definiert oder über die Render-Funktion flexibel angepasst werden. Mit GUIs wie 'Knit with Parameters' ist das Setzen und Anpassen sogar noch benutzerfreundlicher!",
incorrect = "Leider falsch, Parameter werden im YAML-Header oder über die Render-Funktion gesetzt, um flexibel und interaktiv im R Markdown verwendet zu werden.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
)
)
```
---
# **Interaktive Übung**
Wir werden uns nun gemeinsam anschauen, wie wir mit diesen Parametern arbeiten können, um am Ende eine Automatisierung unserer Reports zu ermöglichen.
---
## **Schritt 0: Set-up**
Zunächst ist es wichtig, die richtige Infrastruktur für Eure Reports zu schaffen. Eine Reportautomatisierung besteht aus:
- einem **Reporttemplate in R Markdown**, also einer Vorlage, in der der Inhalt des Reports, der Code und die Parameter im YAML-Abschnitt definiert werden (reporttemplate.Rmd)
- einem **Ausführungsskript**, das die render-Funktion zur automatischen Erstellung der Reports enthält. Hier können verschiedene Optionen für den Prozess der Reportgenerierung eingestellt werden. Außerdem können für Parameter bestimmte Werte definiert werden, die dann über die Platzhalter-Parameter sogar in den Code des R Markdown-Dokuments einfließen können und somit den generierten Report beeinflussen. (Diese Dateien werden oft render.R oder render.Rmd genannt. Wir verwenden report_factory.Rmd.)
Beide Code-Skripte sollten in einem **R-Projekt** eingebettet sein. Wie bereits im Kapitel "Einführung in R(Studio)" erklärt, helfen diese als metaphorischer Umzugskarton, unsere Infrastruktur zusammenzuhalten. Ein R-Projekt, das alle enthaltenen Dateien einbettet, erleichtert die Übergabe der Werte zwischen den Dateien. Nützlich sind zudem die **Ordner "daten"**, in dem alle Daten hinterlegt sind, sowie der **Ordner "out"**, in dem alle erzeugten Reports gespeichert werden.
---
## **Schritt 1: Parameter definieren**
Um Parameter nutzen zu können, müssen diese **immer** im YAML-Header definiert werden. Der folgende YAML-Header legt als Titel "Mein Report", als Autor:in "Maxi Mustermensch", als Datum den heutigen Tag (`r params$heute`) und als Output ein HTML-Dokument fest. Darüber hinaus setzen wir eigene Parameter (params). Jede Zeile folgt der Logik eines **Key-Value-Paares** (zu dt. Schlüssel-Wert-Paar). Die Bezeichnung des Wertes steht also vor dem Doppelpunkt, der Wert danach (`parameter_name(key): parameter_wert(value)`). Dieser Wert ist Euer Standardwert bei der Ausführung des Codeskripts. Wenn dieser leer bleibt, wird er automatisch auf `NULL` gesetzt.
---
title: "Mein Report"
author: "Maxi Mustermensch"
date: "`r format(Sys.Date(), '%d. %B %Y')`"
output: html_document
params:
heute: !r format(Sys.Date(), '%d. %B %Y')
daten: "daten/audit.csv"
filter_plastic: "hdpe"
filter_continent: "alle Kontinente"
---
In diesem Fall haben wir als Parameter das Ausstellungsdatum des Reports (den aktuellen Tag), den Datensatz, den Plastiktyp sowie einen Parameter mit verschiedenen Ausprägungen (Kontinente) definiert. Da wir diese Parameter bei der Erstellung und Aktualisierung von Reports häufig austauschen, dienen sie als flexible Einstellungen, die wir regelmäßig anpassen können.
*Anmerkung: Achtung bei der Nutzung von R-Funktionen in den allgemeinen YAML-Headereinstellungen und den Parametern. Wie Ihr in der Zeile des Parameters "heute:" seht, unterscheidet sich die Syntax von den anderen Parametern.*
---
## **Schritt 2: Parameter einbinden**
Parameter, die im YAML-Abschnitt definiert wurden, stehen als **Liste namens `params`** zur Verfügung. Als Nächstes müssen wir RStudio signalisieren, dass diese Parameter in unseren Report eingebunden werden sollen. Um auf einen Parameter im Code zuzugreifen, verwenden wir `params$parameter_key`. Auf den Parameterwert können wir sowohl in Code-Chunks als auch im Inhalt des R Markdowns zugreifen. Schauen wir uns das Beispiel des Parameters "heute" an:
````
Das heutige Datum ist: `r knitr::inline_expr('params$heute')`
````
Beim Rendern des R Markdowns wird der Platzhalter `params$heute` durch das Datum ersetzt, das im YAML-Abschnitt definiert wurde. Aus dem Code wird dann:\
````
Das heutige Datum ist: `r params$heute`.
````
Genauso funktioniert das Ganze auch für Code:
```{r, parameter_call, exercise = TRUE}
# Zugriff auf den Parameter "heute"
print(params$heute)
```
Im oberen YAML-Header haben wir einen weiteren Parameter für die **Plastikarten** definiert: `filter_plastic: "hdpe"`. Versucht einmal, diesen definierten Filter auszugeben bzw. zu drucken (engl. print):
``` {r 11quiz_parameter_call, exercise = TRUE}
# Hier Euer Code!
```
```{r 11quiz_parameter_call-solution}
# Zugriff auf den Parameter "filter_plastic"
print(params$filter_plastic)
```
```{r 11quiz_parameter_call-check}
grade_this_code()
```
<!-- Die Parameter können wir dann nutzen, um Daten einzulesen... -->
<!-- ```{r parameter_daten, exercise = TRUE} -->
<!-- # Daten mit Parameter laden -->
<!-- rio::import(here::here(params$daten), fill=TRUE) -->
<!-- ``` -->
Diese Parameter können übrigens auch dazu nutzen, um in unseren Daten zu filtern. Wir verwenden an dieser Stelle den vorbereiteten Datensatz `audit`.
```{r parameter_filtern, exercise = TRUE}
# Laden des Audit-Datensatzes
audit <- rio::import(
here::here("daten/bffp2019_audit_by_country_and_company.csv")
)
```
Diesen Datensatz können wir beispielsweise auf Basis unseres festgelegten Parameters `filter_plastic: "hdpe"` filtern. dabei wenden wir zunächst die Funktion `dplyr::filter()` an, um nur die Zeilen auszuwählen, bei denen die Spalte `plastic_type` mit dem in `params$filter_plastic` festgelegten Wert übereinstimmt. Dadurch können wir flexibel und gezielt Daten für verschiedene Kunststoffarten analysieren.
```{r 11quiz_1-parameter_filtern, exercise = TRUE}
# Filtern des Audit-Datensatzes
audit %>%
dplyr::filter(plastic_type == params$filter_plastic)
```
Werft noch einmal einen Blick auf den oberen YAML-Header, dort haben wir einen zusätzlichen Parameter für die **Kontinente** hinterlegt: `filter_continent: "alle Kontinente"`. Versucht einmal, diesen Parameter zu nutzen, um die Daten zusätzlich nach den Kontinenten zu filtern:
```{r 11quiz_parameter_filter, exercise = TRUE}
# Filtern des Audit-Datensatzes (hinterlegt als )
audit %>%
dplyr::filter(plastic_type == params$filter_plastic)
# Euer Code hier
```
```{r 11quiz_parameter_filter-solution}
# Filtern des Audit-Datensatzes
audit %>%
dplyr::filter(plastic_type == params$filter_plastic,
continent == params$filter_continent)
```
```{r 11quiz_parameter_filter-check}
grade_this_code()
```
```{r 11quiz_reportauto_filter}
quiz(caption = NULL,
question("Wie viele Beobachtungen werden gefunden?",
answer("2886"),
answer("0", correct = TRUE),
answer("178"),
correct = "Richtig, aber wieso ist das so?",
incorrect = "Leider falsch, versuche es einfach nochmal.",
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
),
question("Warum ist das der Fall?",
answer("Es gibt für den Kontinent keine Beobachtungen.", correct = TRUE),
answer("Das muss ein Fehler sein..."),
correct = 'Richtig, wir haben nämlich den Parameter `filter_continent` mit dem Standardwert „alle Kontinente“ definiert. Einen solchen Kontinent gibt es im Datensatz natürlich gar nicht. Das ist jedoch ein praktischer Trick: Auf diese Weise können wir eine Bedingung einbauen. Nur wenn der Parameter spezifiziert ist (also ungleich „alle Kontinente“), wird ein spezifischer Report erstellt. Andernfalls wird der Report für den gesamten Datensatz erzeugt. Cool, oder?',
incorrect = 'Leider falsch, die Anzahl der Zeilen (= Beobachtungen) beträgt 0, wie in `<0 rows> (or 0-length row.names)` zu sehen ist. Wir haben nämlich den Parameter `filter_continent` mit dem Standardwert „alle Kontinente“ definiert. Einen solchen Kontinent gibt es im Datensatz natürlich gar nicht. Das ist jedoch ein nützlicher Trick: Auf diese Weise können wir eine Bedingung einbauen. Nur wenn der Parameter spezifiziert ist (also ungleich „alle Kontinente“), wird ein spezifischer Report erstellt. Andernfalls wird der Report für den gesamten Datensatz erzeugt. Cool, oder?',
allow_retry = TRUE,
try_again_button = "Nochmal versuchen"
)
)
```
Wenn wir dennoch unseren Datensatz nach der festgelegten Plastikart und den einzelnen Kontinenten filtern wollen, können wir beispielsweise folgende Option in die Datenbereinigung einbauen:
```{r filter_trick, exercise = TRUE}
### Filter für parametrisierte Reports einfügen
if (params$filter_continent != "alle Kontinente") {
audit <- audit %>% dplyr::filter(continent == params$filter_continent)
}
# Head drucken
head(audit)
```
Der if-Block überprüft den Wert des Parameters `filter_continent`. Ist dieser **ungleich (`!=`) des Standardwerts "alle Kontinente"**, wird die Bedingung erfüllt und der Filter angewendet. In diesem Fall wird der audit-Datensatz mithilfe der `filter()`-Funktion gefiltert. Dabei werden nur die Zeilen beibehalten, bei denen der Wert in der Spalte `continent` dem in `params$filter_continent` festgelegten Parameterwert entspricht.
---
## **Schritt 3: Parameter anpassen**
Nun wollen wir uns anschauen, wie wir die Parameter entsprechend anpassen können. Dabei gibt es nämlich verschiedene Möglichkeiten:
### **Option A1: YAML-Header**
Falls wir unseren Report lediglich semi-automatisch ausführen wollen, können wir die Parameter **manuell im YAML-Header** jederzeit austauschen und anpassen. Der Report wird dann auf Basis der aktualisierten Parameter ausgeführt (Klickt einfach auf "Knit"). Diese Option ist jedoch nur begrenzt praktikabel, da sie manuelle Eingriffe erfordert und der Prozess ineffizient wird, wenn viele Reports mit unterschiedlichen Parametern generiert werden sollen. Zudem steigt die Fehleranfälligkeit bei häufigen Änderungen, wenn die Parameter jedes Mal direkt im YAML-Header angepasst werden müssen.
### **Option A2: YAML-Header mit GUI**
Neben dem Knit-Button findet sich ein Menü, in dem "Knit with parameters..." ausgewählt werden kann. Daraufhin öffnet sich in R-Studio eine **graphische Oberfläche** (= Graphical User Interface, GUI), in der eigene Werte für die definierten Parameter eingegeben werden können. Allerdings ist auch diese Option nur begrenzt praktikabel, denn die manuelle Eingabe kann zeitaufwändig sein und ist bei der Erstellung mehrerer Reports mit unterschiedlichen Parametern besonders fehleranfällig.
![*Knitting mit Parametern - Standard (Screenshot)*](https://github.com/CorrelAid/rlernen_umwelt/blob/main/abbildungen/11_automatisierte-reports/knitwithparameters.png?raw=true){#id .class width=50% height=50%}<br>
Fun Fact: Sogar das **Layout der Parametereingabe** kann über den YAML-Header gestaltet werden. Dabei stehen die freie Eingabe (Standard), Dateiuploards (nützlich für Daten), Slider (für numeriswche Werte oder Datumsangaben) und ein Dropdown-Menü zur Verfügung. Außerdem können wir den Eingabefeldern individuelle Namen, ein Minimum und Maximum zuweisen. Ein modifiziertes GUI könnte beispielsweise so aussehen:
![*Knitting mit Parametern - Menüoptionen (Screenshot)*](https://github.com/CorrelAid/rlernen_umwelt/blob/main/abbildungen/11_automatisierte-reports/knitwithparametersoptions.png?raw=true){#id .class width=50% height=50%}
---
### **Option B1: Die Render-Funktion mit GUI**
Eine weitere Möglichkeit, die wir Euch vorstellen möchten, ist das Starten der GUI über die `rmarkdown::render()`-Funktion. Diese Methode funktioniert ähnlich wie Option A2: Sie öffnet ebenfalls eine grafische Oberfläche, in der die Parameterwerte für den Report manuell angepasst werden können. Und so lautet die Funktion:
```r
rmarkdown::render("Report_Plastic.Rmd", params = "ask")
```
Mit `params = "ask"` wird ein **Dialog zur Eingabe der Parameter** geöffnet. Allerdings ist diese Option ebenfalls nur begrenzt praktikabel, da auch hier jeder Parameterwert manuell eingegeben und für das erstellen vieler Reports mit unterschiedlichen Parametern immer wiederholt werden muss.
### **Option B2: Die Render-Funktion**
Wenn wir viele Reports auf einmal erstellen möchten, ist das Arbeiten mit der `render()`-Funktion die beste Wahl! Hierfür richten wir eine spezielle **Render-Datei** ein (z. B. `render.R` oder `render.Rmd`), die den gesamten Automatisierungsprozess steuert. In dieser Datei definieren wir die `render()`-Funktion, die es uns ermöglicht, mehrere Reports mit variierenden Parametern in einem automatisierten Durchgang zu erzeugen.
In der `render()`-Funktion werden sämtliche **Aspekte des Reportings festgelegt**: der Pfad zur Vorlage (`input`), das gewünschte Ausgabeformat (`output_format`), der Name (`output_file`) und Speicherort (`output_dir`) der Ausgabedatei sowie die Parameterwerte (`params`), die für jeden Report variieren können. So lässt sich mit nur einem Code-Skript eine große Anzahl an Reports generieren, ohne dass manuelle Eingaben erforderlich sind.
```r
rmarkdown::render(
input = here::here("Report_Plastic.Rmd"), # Hier kommt Euer Reporttemplate hin
output_format = "html_document", # Hier legt Ihr das Outputformat fest
output_file = glue::glue("{lubridate::today()}_Report_{params$filter_continent}"), # Hier legt Ihr den Outputnamen fest
output_dir = "output" # Hier legt Ihr den Ordner fest, in dem Output gespeichert wird
params = list(filter_continent: "alle Kontinente") # Hier könnt Ihr die Parameterliste setzen
)
```
Mit dieser Funktion erzeugen wir automatisch eine **Reportdatei für jeden festgelegten Parameterwert**. Durch Anpassen der Parameterliste `params` können wir Reports für verschiedene Regionen, Zeiträume oder andere Filterwerte erzeugen, ohne dass weitere manuelle Anpassungen erforderlich sind.
---
## **Schritt 4: Die Reportfabrik**
Wenn wir viele Reports auf einmal erstellen wollen, müssen wir die Render-Funktion in etwas einbetten, das definiert, dass der **Report für die verschiedenen Werte in einer Liste gerendert werden soll**. Wir greifen dabei auf das **`purrr`**-Package zurück, welches ebenfalls zum `tidyverse` gehört und verschiedene Funktionen zur **funktionalen Programmierung** in R enthält. Es hilft insbesondere dabei, **wiederholte Aktionen** über Listen, Datenrahmen oder Vektoren effizienter und übersichtlicher durchzuführen. Somit wird der Code oft kürzer und leichter verständlich, besonders wenn wiederholte Berechnungen in Analysen oder bei der Automatisierung anfallen.
<left>
![](https://www.tidyverse.org/css/images/hex/purrr.png){#id .class width="20%" height="100%"}
</left> <br>
Wir verwenden an dieser Stelle die Funktion **`purrr::walk`**, welche eine **Aktion für jedes Element in einer Liste** ausführt, ohne dass ein Rückgabewert-Objekt zurückgegeben wird. Die Funktion läuft einfach durch und führt die jeweilige Funktion aus, die wir im Vorfeld definieren. Dadurch eignet sie sich ideal für Operationen, bei denen es darum geht, **nebeneffekthaltige Funktionen** wie das Schreiben von Dateien oder das Drucken von Nachrichten auf jedes Element einer Liste anzuwenden.
Der grundlegende Ablauf lautet also: **Für jedes Element der Liste (z.B. eine Reihe von Werten oder Objekten), wende die Funktion an, die hier definiert wird.**. Hier ist ein Beispiel:
```r
purrr::walk(liste, function(listenelement) {
beliebige_function(beliebiges_argument = bezug_listenelement)
})
```
Wir wollen für den [Report Ausblick](https://drive.google.com/file/d/1vjfbibPdMfXuw0HQHL_0p4MeGO_kcYP2/view?usp=share_link){target="_blank"}, der bereits den Trick mit "alle Kontinente" enthält, nun ein `render.R`-Skript erstellen. Dieses Skript hilft uns dabei, dass wir für **jeden Kontinent einen eigenen Report** erstellen. Dazu importierten wir in das neue `render.R`-Skript den Audit-Datensatz und erstellen - analog zum Report - den Audit-Datensatz. Da wir für jeden Kontinent einen Report anlegen wollen, benötigen wir eine **Liste** der Kontinente.
```r
# Liste mit Kontinenten erstellen
kontinente_liste <- unique(audit$continent)
```
Im Anschluss kombinieren wir die `purrr::walk()`-Funktion mit der `rmarkdown::render()`-Funktion.
```r
purrr::walk(
.x = kontinente_liste,
.f = ~rmarkdown::render(
# Hier kommt Euer Reporttemplate hin
input = here::here("11_reports-uebung_NH_Ausblick.Rmd"),
# Hier legt Ihr das Outputformat fest
output_format = "html_document",
# Hier legt Ihr den Outputnamen fest, der nun den Kontinent beinhaltet
output_file = glue::glue("{lubridate::today()}_Report_{.x}"),
# Hier legt Ihr den Ordner fest, in dem Output gespeichert wird
output_dir = "output"
# Hier könnt Ihr die Parameterliste setzen: Wir ändern nur den Parameter "Kontinent"
params = list(filter_continent: "alle Kontinente")
)
```
*Tipp 1: Erstellt das zugehörige Directory automatisch, falls es nicht exisiert.*
```r
output_dir <- here::here("output")
if (!dir.exists(output_dir)) {
dir.create(output_dir)
}
```
*Tipp 2: Ihr wollt die Reports ganz automatisch ohne Euer Zutun erzeugen, z.B. auf einem Server? Dafür nutzen wir CronJobs, die zeitbasiert Prozesse für uns ausführen. Wie üblich gibt es zum vereinfachten Management ein Package in R: [cron R Dokumentation](https://cran.r-project.org/web/packages/cronR/cronR.pdf){target="_blank"}*
Tolle Tipps, Tricks und mehr Input findet Ihr auf der [Website von R-Studio](https://rmarkdown.rstudio.com/lesson-6.html){target="_blank"}, in den englischsprachigen Büchern [Markdown: The Definite Guide, Kapitel 15](https://bookdown.org/yihui/rmarkdown/parameterized-reports.html){target="_blank"} und [R Markdown Cookbook, Kapitel 17.4](https://bookdown.org/yihui/rmarkdown-cookbook/parameterized-reports.html){target="_blank"} sowie bei [Dataquest](https://app.dataquest.io/course/intermediate-r){target="_blank"}. In dem verlinkten Kapitel findet Ihr insbesondere weitere Hilfestellungen zu Wenn-Dann-Bedingungen, Funktionen und Iterationen.
---
# **Und jetzt Ihr!**
Wenn Ihr einen **eigenen Report** habt - den Ihr in der [Hauptsession](https://rlernen.correlaid.org/11_reports.html){target="_blank"} erstellt habt - dann könnt Ihr versuchen, diesen mit Hilfe der `rmarkdown::render()` Funktion zu generieren und die Funktion so anzupassen, dass der Dateiname nach euren Wünschen angepasst wird.
Wenn Ihr nicht genug vom Report fabrizieren bekommen könnt oder keinen eigenen Report habt, dann schaut in den Ordner `10_automatisierte-reports/10_automatisiertereports` im [Übungsordner](https://download-directory.github.io/?url=https://github.com/CorrelAid/rlernen_umwelt/tree/main/uebungen){target="_blank"}, öffnet das **R Projekt `11_automatisierteReports.Rproj`** und versucht die Aufgaben in **`Report_Factory.Rmd`** zu bearbeiten.*
---
# **Zusätzliche Ressourcen**
- [RStudio Webinar: **Rethink Reporting with Automation**](https://www.rstudio.com/resources/webinars/rethink-reporting-with-automation/){target="_blank"}
- Yihui Xie et al. [**RMarkdown: The Definitive Guide**](https://bookdown.org/yihui/rmarkdown/parameterized-reports.html){target="_blank"} (engl.)
- RStudios [Hilfeseite](https://rmarkdown.rstudio.com/lesson-6.html){target="_blank"}
- [CorrelTalk: **Automatisierte Reportgenerierung für die Weltläden**](https://soundcloud.com/correlaid_podcast/about-correlaid-eine-interaktive-weltkarte-fur-erlassjahrde?utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing){target="_blank"}
---
<a class="btn btn-primary btn-back-to-main" href=`r params$links$end_session`>Session beenden</a>