Müssen JournalistInnen Programmieren können?

Beispielhafter Python-Code als Teaserbild für diesen Blogpost

Mit meiner Kollegin Anna Behrend aus der Zentralredaktion von NOZ, SHZ und SVZ in Hamburg habe ich neulich in einem Webinar des Netzwerk Recherche über genau dieses Thema diskutiert. Wobei man fairerweise sagen muss: Im Grunde waren wir uns ziemlich einig. Aber ich finde: Die Frage macht im Jahr 2020 total Sinn. Deswegen heute auch ein Blogpost dazu: Sollten Journalisten Programmieren können/lernen?

Ich bekomme immer wieder mit, wie KollegInnen im Datenjournalismus oder im Storytellingbereich gefragt werden, ob man denn als JournalistIn heute auf jeden Fall eine Programmiersprache können muss. Ein spannendes Thema, finde ich.

Ziemlich eindeutig ist die Antwort für Menschen, die als DatenjournalistInnen arbeiten wollen: Ja, lernt Programmieren! Die Szene hat sich immer mehr professionalisiert, man arbeitet in der Regel mit Menschen zusammen, die auch Coden – oder hilft Menschen bei Problemen, die Code vielleicht einfacher/schneller/besser lösen kann.

Die Frage hat Björn Schwentker bereits 2015 auf der Netzwerk Recherche-Jahrestagung für DatenjournalistInnen deutlich beantwortet: „Ich persönlich glaube, dass man Programmieren können sollte.“

Für alle anderen JournalistInnen wäre eine Antwort auf die Frage aber natürlich auch interessant: Ich denke, das kommt sehr darauf an, ob man das auch lernen möchte und was man sich davon verspricht.

Man kann auch in klassischen Recherchen von eigenen Datenauswertungen profitieren (man denke an Finanz-, Gesundheits- oder Sozialpolitik, viele Sportarten oder Wirtschaftsthemen). Es kann in manchen Bereichen Sinn machen, wenn man Algorithmen nicht nur beschreiben, sondern sogar (nach)programmieren kann. Und es macht halt auch einfach Spaß, etwas neues zu lernen, um „Probleme“ zu lösen.

Andererseits muss man so eine Sprache aber natürlich auch lernen. Ihre Syntax, ihre Worte, ihre Stärken, vielleicht auch ihre Schwächen. Und wenn man sich damit noch gar nie beschäftigt hat, muss man sich nebenbei auch noch viel über das Internet, Webschnittstellen, Datenstrukturen, Datenbanken und vieles mehr beibringen. Das kostet Zeit und braucht Frustrationstoleranz. Aber wenn man ein Programm geschrieben hat, das eine bestimmte Funktion ganz smooth und störungsfrei ausführt, fühlt sich das manchmal ein bisschen an wie Magie.

Ich hab mal versucht, fünf Gründe zu beschreiben, warum Programmieren für Journalisten sinnvoll sein kann. Ein Teil davon doppelt sich ein bisschen mit meinem Blogpost zur Automatisierung.

1. Schnelligkeit

Im Journalismus zählt oft jede Minute. Bei Wahlen oder generell bei Veröffentlichungen, die man vorhersehen kann (Hurrikans, Unfallatlas, Abstimmungen aller Art), helfen vorgeschriebene Skripte dabei, dass Aufgaben schneller umgesetzt werden, als wenn das Menschen machen müssen.

Das gilt auch zum Beispiel für das Downloaden und Verarbeiten von vielen Daten, zum Beispiel hundert ähnlichen PDFs zu einem bestimmten Thema. Oft kann man die Arbeitszeit viel sinnvoller einsetzen.

2. Tiefe oder Personalisierung

Manchmal ist es auch gar nicht möglich, dass Menschen eine Menge an Informationen händisch verarbeiten (looking at you, Panama Papers). Dann bleibt nur der Ausweg Computer. Skripte können dann helfen, über große Datenmengen einen Überblick zu bekommen, sie auszuwerten, oder darin zu suchen. Man kann ein Thema dadurch tiefer ausleuchten, als es bei händischer Recherche geht.

Andererseits können Journalisten, die programmieren auch persönlichere Inhalte anbieten. Indem Datensätze nach bestimmen Merkmalen (Region, Alter, Geschlecht, Einkommen) aufgetrennt werden, und sich die Nutzer darin selbst verorten können.

3. Zugänglichkeit

Manche Daten sind vielleicht auch gar nicht in einem tabellarischen Format. Die Klassiker: JSON oder XML, Daten, die man zum Beispiel über APIs bekommt.

Mit ein bisschen Hustle kann man die zwar für Excel et al passend machen – aber in der Regel haben verschachtelte Daten ja auch einen Zweck. Viel praktischer ist es dann doch, wenn man mit diesen Daten direkt weiterarbeiten kann. Und das geht nunmal am einfachsten mit Code, den Journalisten programmieren.

4. Transparenz

Ja, ich kann auch nach einer Excelrecherche Punkt für Punkt mitschreiben, welche Änderungen ich an den Daten vorgenommen habe, was ich ausgewählt habe, welche Buttons ich gedrückt habe. Aber das ist furchtbar unübersichtlich.

Gerade JournalistInnen (aber auch WissenschaftlerInnen) steht es daher gut zu Gesicht, wenn sie ihre Daten und Skripte öffentlich zugänglich machen. Ein Code zeigt mir Schritt für Schritt, was von den Input-Daten bis zu den Output-Daten passiert ist. Darin lassen sich auch Fehler finden, ganz klar. Aber lieber einen Fehler finden und korrigieren, als etwas falsches stehen zu lassen.

Transparenz von Code und Daten geht natürlich nicht bei allen Recherchen (Quellenschutz, Datenschutz, etc.) – aber vermutlich in sehr vielen Fällen. Allerdings muss dafür auch Arbeitszeit investiert werden, denn die Aufbereitung des Codes kostet Zeit.

Im Idealfall kann dann aber auch jede/r zuhause eine Datenanalyse nachvollziehen.

5. Reproduzierbarkeit

Was uns zum letzten Punkt bringt. In der Wissenschaft gilt der große Anspruch, dass Forschung reproduzierbar, also wiederholbar, sein soll. Das macht auch in vielen (wenn nicht fast allen) datenjournalistischen Analysen Sinn. Wenn ich einen Datensatz betrachte, und ihm identische Fragen stelle, sollte die Antwort die gleiche sein. Nur dann kann ich mich darauf verlassen, dass die Aussagen, die ich treffe, auch stimmen.

Außerdem können im besten Fall KollegInnen in anderen Häusern eine Recherche wiederholen. Klingt vielleicht erstmal blöd – aber geht es uns nicht im Grunde darum, Missstände aufzudecken? Wenn man sich dabei gegenseitig unterstützen kann – warum sollte man das nicht tun? Die exklusive Geschichte hatte man ja in der Regel schon bei der eigenen Veröffentlichung.

Welche Programmiersprachen sollten JournalistInnen lernen?

Das ist wohl die häufigste Frage, nach der im Titel dieses Blogposts. Dabei ist meine Antwort: a) „es kommt drauf an“ oder b) „es ist eigentlich relativ egal“. Was meine ich damit?

Für spezielle Zwecke haben sich verschiedene Sprachen herausgebildet: Javascript ist zum Beispiel der Standard für Interaktivität auf Webseiten, PHP steuert oft die Server hinter Homepages, viele Android-Apps werden mit Java geschrieben. Wenn man schon genau weiß, in welchem Bereich man unterwegs sein wird, kann man sich so orientieren.

Andererseits habe ich die Erfahrung gemacht: Wenn man die Grundzüge des Programmierens verstanden hat, kann man relativ einfach auch zwischen Sprachen wechseln. Es wird nur manchmal etwas mühsam, wenn man aus Versehen Fehler einbaut, weil manche Befehle in Sprachen unterschiedlich funktionieren.

Programmieren kann man in vielen Sprachen

Das führt mich zum zweiten Punkt: Es ist ein bisschen egal, welche Sprache man lernt. Das trifft grundsätzlich zu, wenn man gängige Sprachen lernt und dann wechselt – das trifft aber besonders für die zwei gängigen Sprachen im Datenjournalismus zu: Python und R.

Python stammt eher aus der Informatikszene, R aus der Statistik. Python ist daher eher das Allroundtalent, R setzt einen starken Fokus auf statistische Auswertungen und die Kommunikation von Ergebnissen (in Grafiken, HTML, PDFs, Markdown-Dokumenten).

Was aber nicht heißt, dass die riesigen Communities um die beiden Sprachen nicht schon fast jede denkenswerte Erweiterung geschrieben haben, mit denen in Python und R quasi alles möglich ist. So sind Python und R eigentlich Workflow-Programme. Man kann von Anfang bis Ende ein Problem darin bearbeiten.

Programmieren für Journalisten: Lerne eine Sprache gut

Deswegen bleibt am Ende vermutlich nur dieser Tipp: Lerne eins von beidem gut – im Zweifel kannst Du dann auch das andere bedienen, falls Du eine ganz spezielle Funktion willst.

Ich habe mich zum Beispiel recht früh für R entschieden [In einem anderen Post habe ich schonmal beschrieben, wie ich R gelernt habe] – aber Python bekomme ich notfalls auch noch hin, wenn ich es brauche. Inzwischen geht sogar ein bisschen Javascript (was dann aber einfach nochmal neue Möglichkeiten eröffnet – eher in Richtung Datenvisualisierung als für Datenanalyse).

Und wo lernt man? Da gibts quasi für jeden Geschmack das passende (ich finde aber: auf Deutsch gibts zu wenig): Tutorials, Bücher, Workshops auf Konferenzen.

Kostenlose Onlineressourcen:
R for Journalists: Ist aus einem MOOC entstanden, gibts jetzt als digitales Buch
Coding for Journalists in Python: Ähnlich wie R, nur eben in Python
Kostenlose Bücher (gibts auch gedruckt zu kaufen):
R for Data Science (Hadley Wickham)
R Programming for Data Science (Roger D. Peng)
Und natürlich gibts auch kostenpflichtige Kurse (mit mehr Anleitung und kleineren Schritten):
Der Klassiker: Datacamp (150-300 US-Dollar im Jahr)
Coursera
EdX
Auch gut:
Journocode,
das Lede-Programm in New York,
Seminare, wie das ifp-Coding-Cootcamp [Disclaimer: Da hab ich auch schon unterrichtet]
oder Studiengänge an den Unis Leipzig, Dortmund oder in Cardiff

Fazit: Programmieren kann für viele Journalisten Sinn machen – für Datenjournalisten ist es inzwischen Standard.

Auch Anna hat ein paar Punkte aus unserem Gespräch zusammengefasst:

4 Tipps für automatisierte Grafiken mit DatawRappr

Das Coronavirus hat im digitalen Journalismus viel angeschoben. Zum Beispiel beim Thema automatisierte Grafiken. Ein paar Tipps, wie ich mit Skripten und Datawrapper Grafiken update.

Dieser Blogpost ist schamlose Werbung für mein R-Package DatawRappr. Das hatte ich zufällig Ende 2019 entwickelt, hauptsächlich um die API von Datawrapper aus R heraus nutzen zu können.

Inzwischen nutzen es viele DatenjournalistInnen, um ihre Grafiken für das Coronavirus zu updaten. Seit Beginn der Pandemie habe ich einige Lösungen damit entwickelt, um „fancy“ Sachen zu machen – ein paar davon wollte ich hier teilen. Ein bisschen nerdiger Post diesmal.

1. Viele Grafiken auf einmal erstellen

Ein klassischer Anwendungsfall: Wir haben eine Grafik und hätten die gerne für verschiedene Ausprägungen ausgegeben. Zum Beispiel: Ein Liniendiagramm der Neuinfektionen für alle Länder in der EU. Wie kann ich diese Grafiken – die alle gleich aussehen – am einfachsten hintereinander weg erstellen?

Das geht ganz einfach über einen For-Loop (R-Enthusiasten werden an dieser Stelle darauf hinweisen, dass man dafür doch auf jeden Fall die apply-Familie oder das Package purrr verwenden sollte. Macht auch Sinn, aber vermutlich ist es für Leute aus anderen Programmiersprachen einfacher, wenn wir erstmal bei for bleiben.)

Wie gehen wir vor?

  1. Wir erstellen für ein Land die Grafik in Datawrapper so, wie sie aussehen soll.
  2. Lade die Metadaten dieser Grafik in R: metadata_chart <- dw_retrieve_chart_metadata(chart_id, api_key)
  3. Wir speichern den visualize-Abschnitt der Metadaten lokal ab. Zum Beispiel als visualize.RData:
    visualize <- metadata_chart[["content"]][["metadata"]][["visualize"]]
    saveRDS(visualize, "visualize.RData")
  4. Visualize enthält alle optischen Vorgaben unserer Grafik. Wir können die der API mitgeben, wenn wir eine neue Grafik erstellen.
    Jetzt geht also der Loop los – über einen Vektor mit den Ländern. Grundsätzlich sieht der irgendwie so aus:
    for (Land in Laender_liste) {
    rohdaten %>%
    filter(Staat_in_Rohdaten == Land)
    }
  5. Für jedes dieser Länder erstellen wir eine neue Datawrapper-Grafik mit dw_create_chart(). Die neue Chart-ID bekommen wir direkt von der API zurückgeliefert und können sie im weiteren Verlauf benutzen:
    current_chart <- dw_create_chart(title = paste0("Chart für ", Land),type = "d3-lines")
  6. Damit auch die Visualisierungen richtig angezeigt werden, schicken wir der neuen Grafik direkt noch ein dw_edit_chart() hinterher:
    dw_edit_chart(chart_id = current_chart, visualize = visualize)
    [Eventuell kann man an dieser Stelle auch schon Daten mit dw_data_to_chart() hochladen.]
  7. Praktisch wäre es jetzt noch, wenn wir einen Überblick bekämen über alle Iframes und URLs unserer neu erstellten Grafiken. Dafür nutzen wir die dw_publish-chart-Funktion. Die kann ein Objekt zurückgeben, das die gewünschten Infos enthält und die wir abspeichern.
    Vor unseren Loop erstellen wir dafür eine leere Liste…
    result_list <- list()
    … die wir in jedem Loop-Durchgang (also für jedes Land) weiter befüllen:
    published_chart <- dw_publish_chart(current_chart)

    result_list[[i]] <- data.frame(id = area_id, country = area_name, url = published_chart$publicUrl, iframe = published_chart$iframeCode, chart_id = published_chart[["content"]][["data"]][[1]][["id"]])
  8. Die Grafiken sind erstellt. Damit wir beim Aktualisieren auch alle Chart-IDs beisammen haben, speichern wir result_list am besten irgendwo lokal als Dataframe ab:
    result_df <- dplyr::bind_rows(result_list)
    saveRDS(result_df, "chart_ids.RData")
  9. Für die Aktualisierung loopen wir dann einfach über result_list und verändern die Charts: die Daten mit dw_data_to_chart, die Titel, Introtexte oder Anmerkungen mit dw_edit_chart.

Den gesamten Code für so einen Loop habe ich hier in einem Github Gist verlinkt.

2. Datawrapper-Grafiken als Bilder ausgeben

In einem weiteren Schritt können wir aus den vielen Grafiken auch Bilder erstellen. Zum Beispiel für einen Small-Multiple-Überblick sein. Also viele kleine Grafiken nebeneinander.

Wir können dafür wieder den vorherigen Loop verwenden. Dazu die Funktion dw_export_chart():
png_chart <- dw_export_chart(
chart_id = current_chart,
type = "png",
unit = "px",
mode = "rgb",
width = 200,
height = 300,
plain = TRUE,
scale = 2)

In diesem Beispiel geben wir ein PNG mit 200 Pixeln Breite und 300 Pixeln Höhe aus, doppelt skaliert (scale), Titel und Anmerkungen werden nicht angezeigt (wegen: plain = TRUE). Mit der Funktion image_write aus dem magick-Package können wir die Grafiken dann lokal speichern:

image_write(png_chart, "output.png")

Dann laden wir die Bilder irgendwo hoch, und bauen mit HTML eine Überblicksseite, in die wir alle einbinden.

3. Tooltips über die Datawrapper-API verändern

Karten und Scatterplots in Datawrapper können beim Hovern oder Klicken Tooltips anzeigen. Auch die kann man ziemlich einfach über die API verändern. Das kann zum Beispiel praktisch sein, wenn man bestimmte Daten dynamisch dazugibt oder eben nicht.

Ein Beispiel: Ich scrape für eine Zusatzinfo eine bestimmte Seite. Diese Info will ich eigentlich immer in meiner Grafik anzeigen, aber was, wenn die Seite plötzlich offline ist? Ich könnte auf ein Fallback zurückspringen, ich kann mich aber auch entscheiden, diese Info dann nicht anzuzeigen. Dafür muss ich die Tooltips verändern können.

Am einfachsten ist das Vorgehen, wenn ich die Tooltips über das grafische Nutzerinterface anlege. Ich kann sie dann über dw_retrieve_chart_metadata() ganz einfach abrufen und verändern. Der Tooltip liegt unter: metadata_chart[["content"]][["metadata"]][["visualize"]] und besteht aus drei Abschnitten:

  • body: ist der Haupttext des Tooltipps. Der Inhalt kann mit HTML und CSS strukturiert werden (wie auch im GUI). Um Variablen aus den Daten zu verwenden nutzt man dieses Format: {{ variable_name }}.
  • title: ist – wie der Name vermuten lässt – die Überschrift des Tooltips. Auch hier kann man Variablen verwenden, wie im body.
  • fields: ist eine Liste, die die Zuordnung von Variablen im Tooltip und Variablen in den Daten festlegt. Zum Beispiel so:
    fields = list(
    "variableTooltip1" = "VariableData1",
    "variableTooltip2" = "VariableData2"
    )
    Im einfachsten Fall heißen die beiden Variablen einfach auf beiden Seiten gleich.

Um den Tooltip zu verändern nutzen wir dw_edit_chart():

dw_edit_chart(chart_id, visualize = list(
tooltip = list(
body = "{{ variableTooltip1 }} has value {{ variableTooltip2 }}.",
title = "{{ variableTooltip1 }}",

fields = list(
"variableTooltip1" = "VariableData1",
"variableTooltip2" = "VariableData2"
)
)))

Screenshot einer Datawrapper-Grafik mit einem Tooltip über einer Deutschland-Karte

4. Kartenlegende handy-freundlich

Datawrapper hat inzwischen richtig viele Möglichkeiten, Karten zu erstellen. Gerade bei Choroplethenkarten gibt es aber ein Problem: Auf kleinen Bildschirmen wird die Karte so weit zusammengestaucht, dass die Legend oft Teile der Daten überlagert – und manche Bereich dadurch nur schwer zu lesen sind. Ein Workaround ist es, den Zoom einzuschalten. [Edit: Am 29.09.20 hat Datawrapper ein großes Update veröffentlicht – mit neuer Legende]

Eine andere Variante: Die Legende in die Unterzeile der Grafik zu verlagern. So geht man dafür vor:

  1. Erstelle eine Choroplethenkarte in Datawrapper: Suche eine Basiskarte aus, und verbinde die Karte mit den Daten (über eine gemeinsame Spalte, z.B. die AGS, oder ISO-Codes). Überprüfe dann einmal kurz, ob die Legende auf der Karte richtig angezeigt wird. [Das geht auch mit DatawRappr]
  2. Lade die Metadaten der Karte in einem R-Skript: metadata_chart <- dw_retrieve_chart_metadata(chart_id, api_key)
  3. In metadata_chart finden wir dann alle Infos, die unsere Karte beschreiben. Die Legende finden wir im Abschnitt metadata_chart[["content"]][["metadata"]][["visualize"]][["categories"]]. Der Einfachheit halber können wir diesen Abschnitt auch einfach schnell als Variable rausziehen:
    new_legend <- metadata_chart[["content"]][["metadata"]][["visualize"]][["categories"]]
  4. Diesen Abschnitt geben wir in die neue Funktion dw_legend_to_string. Sie gibt die Legende dann als HTML-Code zurück (alternativ auch als Textstring oder Vektor), die wir einfach als Unterzeile in Datawrapper hinterlegen können:
    intro_text <- dw_legend_to_string(new_legend, return_val = "html")
  5. Wir updaten die Grafik mit:
    dw_edit_chart(chart_id, api_key, intro = intro_text)

So sieht das Ergebnis aus:

Screenshot einer Datawrapper-Karte mit einer Legend, die handyfreundlich ist.

Wie Datenjournalisten über das Coronavirus berichten

Es gibt momentan nur ein Thema: das Coronavirus. Covid-19 bringt Nachrichtenwebseiten Rekordzugriffszahlen und Datenjournalisten große Aufmerksamkeit. Allerdings birgt das Thema auch manche Probleme. Ein paar Gedanken.

Mysteriöse Lungenkrankheit in Zentralchina ausgebrochen

dpa, 31. Dezember 2019

So lautet die Überschrift einer kleinen Meldung der dpa am Ende des vergangenen Jahres. 27 Erkrankte hatten die Gesundheitsbehörden in Wuhan damals vermeldet. Heute, knapp vier Monate später, liegt die Zahl der bestätigten Coronavirus-Infizierten weltweit deutlich über der Millionenmarke.

In Deutschland leben wir seit einigen Wochen unter Ausnahmebeschränkungen, wir arbeiten teilweise von zuhause, gehen kaum noch raus, treffen keine anderen Menschen. Es wundert daher vermutlich kaum, dass die Menschen in dieser Zeit ein sehr hohes Informationsbedürfnis haben. Sehr erfreulich für die „klassischen Medien“ ist die Beobachtung, dass die Nutzer dieses Bedürfnis anscheinend verstärkt auf den Nachrichtenwebseiten und im öffentlich-rechtlichen Rundfunk gestillt haben möchten. Nicht auf Seiten mit „alternativen Fakten“ oder Verschwörungstheorien im Internet. Auch wenn diese durchaus auch aufblühen.

Gerade für Datenjournalisten gibt es in dieser Krise viel zu tun:

  • Es gibt sehr viele Daten, die verständlich visualisiert werden sollten.
  • Es gibt viel Unsicherheit in den verwendeten Modellen, die richtig interpretiert und kommuniziert werden muss.
  • Es herrscht ein enormer Druck, neue Entwicklungen zeitnah abzubilden, ohne „falsche“ Zahlen zu verbreiten.
  • Andererseits gibt es keine „richtigen“ Zahlen. Denn wir werden nie die korrekte Zahl aller Infizierten abbilden können. Auch das müssen wir immer wieder klarmachen.

Zu Beginn der Krise ging es uns hauptsächlich um klassische Visualisierungen. Vor allem ging es um die Frage: Wie groß ist die Zahl der Infizierten anderswo? Solange das Virus nur in China nachgewiesen war, gab es eine zentrale Quelle. Doch dann begann es auch in anderen Staaten aufzutauchen. Wir brauchten eine neue Quelle, die im Idealfall die ganze Welt abdeckt.

Wo kommen die Daten her?

Vor allem zu Beginn des Coronvirus-Ausbruchs in China (und für alle Länder außer Deutschland auch weiterhin) haben wir die Daten der Johns-Hopkins-Universität verwendet. Die Forscher dort sammeln die Daten zu Infizierten und Verstorbenen pro Land in einem Dashboard, das mehrmals am Tag aktualisiert wird. Und machen die zugrundeliegenden Daten einmal täglich auch über ein Github-Repository zugänglich. Bis Mitte März wurden außerdem die Zahlen der genesenen Patienten veröffentlicht. Das wurde inzwischen eingestellt. Vermutlich ist die Arbeitslast deutlich gestiegen, seitdem Covid-19 auch in den USA angekommen ist – denn für dort ermittelt die Johns-Hopkins sogar die Zahl der Tests.

Johns-Hopkins ermittelt die Zahl nicht nur aus offiziellen Bekanntmachungen, sondern arbeitet unter anderem auch mit Medien zusammen, die kleinräumigere Daten sammeln und vor allem schneller sein sollen, als die amtlichen Statistiken. Denn je schneller wir wissen, wie sich die Zahlen verändern, umso schneller können Politik und Medizin darauf reagieren.

Die deutschen Zahlen für das JHU/CSSE-Dashboard kommen über Umwege von den Kolleginnen und Kollegen des Funke Interaktiv-Teams – die sie wiederum von den Landesgesundheitsämtern sammeln:

Der Inhalt ist nicht verfügbar.
Bitte erlaube Cookies, indem du auf Übernehmen im Banner klickst.

Außerdem nutzt die JHU Zeit Online und den Berliner Tagesspiegel als Quelle. Vermutlich über den Umweg Worldometers, einer Datenwebseite des Unternehmens Dadax. [Tagesschau.de hat versucht, das nachzuzeichnen.]

Fazit: Die Johns-Hopkins ist eine gute Quelle für die weltweiten Zahlen. Vermutlich nicht stundenaktuell, aber für einen Eindruck ausreichend. Aber gerade für Deutschland und die einzelnen Bundesländer wollen wir eigentlich aktuellere und direktere Daten. Die erste Anlaufstation wäre die zuständige Stelle auf Bundesebene:

Probleme mit dem Robert-Koch-Institut

Das Robert-Koch-Institut wurde in der Berichterstattung immer wieder kritisiert. Teilweise dauerte es mehrere Tage, bis die Zahlen dort den Stand der Johns-Hopkins-Zahlen erreichten. Der Grund: Der lange amtliche Übertragungsweg über die Gesundheitsbehörden der Kreise, zu den Gesundheitsministerien der Länder, zum RKI. [Mehr zu diesem Prozess hat mein Kollege Christian Endt hier aufgeschrieben.] Inzwischen sind die Zahlen des RKI auf ein neues, elektronisches Meldesystem umgestellt worden. Aber eine Verzögerung lässtsich auch dadurch nicht vermeiden. Wir versuchen deshalb, wo es geht, auf die RKI-Zahlen zu verzichten.

Wie machen das andere Länder (zugegebenermaßen immer mit anderen Vorraussetzungen)?

  • Sciensano, das belgische Gesundheitsinstitut, publiziert inzwischen die Zahl der Infizierten, die Zahl der Tests, die Zahl der Covid-19-Patienten im Krankenhaus und die Zahl der Verstorbenen täglich auf Provinzebene. Und das ganze als Excel, CSV und JSON – also herausragend machinenlesbar.
  • Italien veröffentlicht seine Infiziertenzahlen in einem Dashboard und als Open Data (sogar in Englisch) auf Github.
  • Sogar der „berüchtige“ britische NHS lässt einen Teil seiner regulären Datensammlungsaufgaben ruhen, um mehr Kapazitäten für die Daten zu Covid-19 zu haben.

Auch das Robert-Koch-Institut ermöglicht über ein Dashboard seit etwa einer Woche auch den Zugang zu sehr viel kleinräumigeren Daten, als zu Beginn der Krise. Und dank dem Geodaten-Anbeiter ESRI werden die Daten hinter dem Dashboard als Open Data angeboten.

Das bedeutet übrigens nicht, das das RKI gerade einen besonders schlechten Job macht. Immerhin werden überhaupt Daten veröffentlicht. Und zwar sehr regelmäßig und mit zunehmender Detailtiefe. Aber: Der langsame Start und die Probleme bei der Übermittlung (teilweise kommen am Wochenende aus manchen Orten keine Meldungen) zeigen einfach, wie schlecht es um Open Data in vielen Bereichen der öffentlichen Verwaltung in Deutschland bestellt ist. Wen das genauer interessiert, der sei auf die Experten dazu verwiesen: zum Beispiel die OpenKnowledgeFoundation.

Es gibt auch private Datensammler

Dass die Datenbasis in Deutschland besser wird, haben wir Initiativen wie Risklayer zu verdanken. Das ist eine Kooperation des Center for Disaster Management and Risk Reduction Technology (CEDIM) am Karlsruher Intitut für Technologie undRisklayer, einer Analysedatenbank zur Risikobewertung. In Kombination mit einem Crowdsourcing und smartem Webscraping werden so viele Quellen (Landesgesundheitsämter und lokale Behörden) kombiniert. Das Ergebnis: Ziemlich aktuelle und kleinräumige Daten. (Eine weitere, wenn auch inoffizielle Quelle ist coronavirus.jetzt). Bei dem Tagesspiegel habe ich Risklayer auch schon als Quelle in Grafiken entdeckt.

Wie wir unsere Coronavirus-Daten sammeln

Auch wir standen vor dem Problem, wie wir unseren Leserinnen und Lesern aktuelle Zahlen, am besten für alle Bundesländer anbieten können. Dabei haben ein paar Kollegen aus der Politikredaktion ein einfaches Verfahren entwickelt: Ein Googlesheet. Sie recherchieren für jedes Bundesland die aktuellsten Zahlen und tragen sie in das Sheet ein. Der Vorteil: Wir müssen uns nicht auf eine Quelle verlassen, die möglicherweise langsam ist. Der Nachteil: dieser Job bleibt bei Menschen hängen.

Damit wir diese Menschen dafür an anderer Stelle entlasten, haben wir sehr viele Grafiken automatisiert. [Wer sich für die Skripte dahinter interessiert, findet einen Stand auf dem SZ-Github-Account. Die Automatisierung funktioniert über das DatawRappr-Package]. Jede halbe Stunde werden inzwischen an die zehn Grafiken automatisch auf den neuesten Stand gebracht. Ohne, dass jemand händisch etwas dafür tun muss.

Für die deutschen Bundesländer verwenden wir also Daten aus der eigenen SZ-Recherche, für die ganze Welt nehmen wir Johns-Hopkins. Aktuell haben wir noch eine Karte mit den deutschen Kreisen – dafür nehmen wir Daten des RKI, normalisiert auf 100.000 Einwohner.

Normalisierte Karten zum Coronavirus?

Über die Frage „Normalisieren oder nicht?“ gab es einige Diskussionen unter deutschen Datenjournalistïnnen auf Twitter. Als es nur wenige Fälle weltweit (oder auch in Deutschland gab) plädierten viele (auch wir) dafür, die Zahl der Fälle absolut zu zeigen, als Kreise. Warum?

Je kleiner die Zahl der Fälle, umso eher steckt dahinter eine einmalige Ansteckungsgeschichte. Die Kappensitzung im Kreis Heinsberg, mutmaßlich das Starkbierfest in Mitterteich. Diese Fälle stechen heraus. Solange ein Virus nicht halbwegs regional breit gestreut ist (wie Verbrechen oder Autounfälle) macht eine Normalisierung wenig Sinn. Ja, in China leben viele Menschen. Ja, die Ansteckung durch ein Virus hängt bestimmt auch damit zusammen, wie dicht Menschen zusammentreffen. Aber eben nicht nur. Außerdem (so mein Eindruck) interessiert viele Menschen die absolute Zahl der Erkrankten in ihrer Nähe. Wir haben deswegen lange auf eine Normalisierung verzichtet. Inzwischen nutzen wir sie auf der oben angesprochenen Karte der deutschen Landkreise.

Aber: Solche Entscheidungen bleiben nicht ohne Debatte. Innerhalb und außerhalb des Teams.

Der Inhalt ist nicht verfügbar.
Bitte erlaube Cookies, indem du auf Übernehmen im Banner klickst.

Von Grafiken zum Coronavirus-Dashboard

„FlattenTheCurve“ geisterte vor wenigen Wochen durch soziale Netzwerke. Eine wesentliche Variable davon ist aber auch: Die Verdopplungsrate. Wie schnell verdoppelt sich die Zahl der Infizierten? Bundeskanzlerin Merkel gab die Marke von zehn Tagen aus, ab der man über die Aufhebung der Ausgangsbeschränkungen sprechen könnte. Diese Verdopplungszahl haben wir seit einigen Wochen als festes Element in einem Dashboard auf der Homepage untergebracht. Sie soll ein bisschen weiterführen. Und ist eine eigene Berechnung aus den vorhandenen Daten.

Das Corona-Dashboard auf SZ.de

Vor allem bei der Spalte „Trend“ haben wir gemerkt, wie hoch das öffentliche Interesse aktuell ist. Noch nie habe ich so viele Lesermails bekommen. Sehr interessant war, wie sich die Menschen darin geäußert haben. Während die Debatte auf Twitter in vielen Fällen sachlich und konstruktiv war (auch das ist bemerkenswert), hatten wir in vielen Mails das Gefühl, man wollte uns grundsätzlich unterstellen, dass wir keine Ahnung hätten und unsere Darstellung völlig falsch sei. Als ob wir uns nichts dabei gedacht haben. Die konstruktiven Mailschreiber haben aber dankenswerterweise viel wertvolles Feedback geschickt.

Wie die Datenjournalistenszene mit Covid-19 umgeht

Sehr schön finde ich den Ansatz, dass inzwischen fast jedes DDJ-Team ein Dashboard produziert hat. Alle haben einen bisschen anderen Angang – ich halte die Grundidee aber für total richtig, solange man mit einem Dashboard weiterhin eine Art „Story“ erzählen kann.

Es ist sehr spannend zu sehen, welch tolle Projekte das traurige Thema Coronavirus möglichmacht. Ich werde hier bestimmt ein relevantes vergessen, deswegen nur ein paar Beispiele:

Was können wir bis hierhin lernen?

  • Austausch mit anderen Datenjournalisten hilft enorm, die eigene Arbeit zu verbessern. Und um zu sehen, dass alle ähnliche Probleme haben.
  • In der Krise liegen Chancen – wir haben einen richtig hohen Output aktuell, können also auch viele neue Erzähl- oder Visualisierungsformen ausprobieren.
  • Die Datenbasis ist nicht optimal. Aber sie verbessert sich. Das ist ein gutes Zeichen.
  • Die FT, allen voran John Burn-Murdoch, sind die aktuellen Sterne am Datenjournalistenhimmel. Nicht nur, aber auch wegen dieser Grafik:
Screenshot Financial Times Coronavirus-Dashboard
Corona-Grafik der FT

Die FT traut sich an ziemlich verrückte Darstellungen. Das hängt vermutlich auch mit ihrem eher zahlenaffinen Publikum zusammen. Um es einen Kollegen vom Spiegel formulieren zu lassen:

Der Inhalt ist nicht verfügbar.
Bitte erlaube Cookies, indem du auf Übernehmen im Banner klickst.

Das Coronavirus wird uns noch lange begleiten. Wenn man darin etwas Positives sehen will: Es hat die Datenjournalistenszene auf jeden Fall zu tollen Projekten angeregt.

Anmerkung:
Seit der Veröffentlichung habe ich einige Fakten im Text korrigiert:
Risklayer war nie eine Quelle von Zeit Online. Die sammeln ihre Daten in Kooperation mit Coronovirus.jetzt.
Die Daten der Johns-Hopkins-Universität für Deutschland haben neben Funke Interaktiv mindestens noch Zeit Online und den Tagesspiegel als Quelle. Tagesschau.de und NDR Data haben mehr dazu recherchiert. (Danke für den Hinweis, Julius)

Automatisierte Wohnungssuche in München

Teaserbild Wohnung München Skript Python

Wie ich mit einer eigenen App versucht habe, eine Wohnung in München zu finden.

Es ist ziemlich einfach, auf Partys in München ein gemeinsames Thema zu finden: den Wohnungsmarkt. Ja, in München sind Mieten in vielen Fällen sehr hoch (wer das nicht glaubt, kann es hier, oder hier nachlesen). Und was noch ein weiteres Problem ist: Eine Wohnung zu finden, ist richtig schwer. Und trotzdem versucht man es. Denn hier zu leben hat ja durchaus Vorteile.

Vor einigen Jahren bin ich auf einen Blogpost von Karim Jedda gestoßen. Er arbeitet im Bereich Automation – und hatte das gleiche Problem, wie viele andere Leute: Wo bekomme ich eine Wohnung her? Sein Vorteil: Er konnte den Prozess automatisieren. Und nutze das gleich für ein Sozial-Experiment mit verschiedenen Namen, Herkunft und Nachrichten:

„a girl with an italian name, gets an 90% answer rate, a guy with an arab name and is younger than 25 gets, 1% answer rate. The master of all, is the young munich guy who is around 25 , called Hanz who almost gets an answer all the time. “

Karim Jedda auf seinem Blog

Wem dieser Versuchsaufbau bekannt vorkommt: Karim war auch an dem spannenden BR Data/Spiegel Online-Datenprojekt Hanna und Ismael beteiligt. Das Projekt versuchte, Diskriminierung am Mietmarkt zu messen.

Aber dieser Aufbau kann auch dem ganz einfachen Zweck dienen, eine neue Wohnung zu finden.

Die Grundannahme dabei: Wohnungsbesitzer stellen ihre Wohnung auf einem der gängigen Immobilienportale ein und werden dann mit hunderten von Bewerbungen überschüttet. Und schauen sich dann vielleicht nur die ersten Bewerbungen an. Sind da passende potenzielle Mieter dabei, werden sie eingeladen. Der Trick ist also, unter diese ersten Mails zu kommen. Am besten, indem man möglichst schnell von neuen Wohnungen erfährt.

Wie eine automatisierte Wohnungssuche aussehen könnte

Auch ich habe vor einigen Jahren eine neue Wohnung in München gesucht. Und habe dann darüber nachgedacht, meine Datenskills dafür einzusetzen.

Es gibt ja wirklich diverse Portale, die Wohnungen anbieten. Vermutlich verstößt es gegen deren AGB, wenn man diese Angebote automatisiert alle paar Minuten abgreifen würde. Technisch wäre das allerdings gar nicht so aufwendig.

Ich will das mal in einem – natürlich rein hypothetischen 😉 – Beispiel in der Programmiersprache Python (Version 2.7) skizzieren:

  • Wir benutzen für das Scraping der Angebote verschiedene Libraries: urllib.request, um Webseiten zu öffnen; BeautifulSoup, um die Daten aus den HTML-Seiten zu „scrapen“ (mehr dazu hab ich übrigens schonmal gebloggt); damit wir nicht so auffallen, können wir fake_useragent benutzen. Das so tut, als käme unsere Anfrage nicht von einem Skript, sondern von einem Browser.
  • Die Daten, die dabei anfallen würden, könnten wir in eine Datenbank schreiben. Ganz easy ist zum Beispiel sqlite. Dafür laden wir die Library sqlite3 und erstellen ein entsprechendes Schema:
Screenshot Datenbank Wohnungssuche Schema
Ein mögliches Datenbankschema für die Immobiliensuche.
  • Zu einem festgelegten Zeitpunkt (also alle paar Minuten) rufen wir die Wohnungs-Webseiten auf uns speichern die für uns relevanten Daten in die Datenbank.
  • Damit wir keine Daten doppelt schreiben, arbeiten wir mit IDs. Steht eine ID schon in der Datenbank, wird ein Eintrag nicht übernommen.
Screenshot Datenbank Wohnungssuche Inhalte
So könnte eine solche Wohnungs-Datenbank aussehen. Adressen sind unkenntlich gemacht.
  • Ein zweites Skript prüft nach jedem Durchlauf, ob neue Einträge/IDs in der Datenbank stehen. Wenn ja, sendet es eine E-Mail mit den neuen Wohnungsangeboten an mich. Das hat der folgende Codeblock ausgelöst:

Ich hab mich ehrlicherweise nicht getraut, automatisierte Mails zu verschicken. Denn ich glaube, dass es viel Sinn macht, in den Mails auf die angebotene Wohnung einzugehen – das können automatisierte Mail-Templates nur zu einem kleinen Teil leisten (indem sie Daten übernehmen, die eindeutig im Angebot stehen – Preis, Quadratmeter, Viertel, …).

Die Pointe am Ende ist übrigens sehr ähnlich zu der im Blogpost auf Funnybretzel. Ich habe eine Wohnung in München gefunden, allerdings nicht im Internet. Sondern ganz klassisch: über eine Zeitungsannonce.

Automatisierung im Journalismus: Wenn das Skript Texte schreibt

Teaserbild Automatisierung

Schneller, tiefgehender und persönlicher sollen die Inhalte werden: Automatisierung im Journalismus ist ein ziemlich neues Feld. Und ein ziemlich spannendes.

Es ist eine Horrorvorstellung für viele Arbeitnehmer: Entlassen, weil der eigene Job jetzt von einem Computer gemacht werden kann. Besser und billiger. Zwischen 75 und 375 Millionen Jobs könnte das bis 2030 treffen, hat eine Studie von McKinsey mal geschätzt. Was man dabei aber nicht vergessen darf: Neue Jobs entstehen.

Im Journalismus sind das beispielsweise Berufsbilder im Automation-Bereich (im Deutschen oft unter dem Begriff „Roboterjournalismus“ – als ob da eine Maschine säße und in die Tastatur eintippt…). In den USA gibt es schon einige Newsrooms mit Automation-Editors, auch der BR startet gerade ein Automation und AI-Lab:

Der Inhalt ist nicht verfügbar.
Bitte erlaube Cookies, indem du auf Übernehmen im Banner klickst.

Und tatsächlich steckt sehr viel Potenzial im Bereich Automatisierung und Journalismus. Der US-amerikanische Journalistikforscher Nick Diakopoulos hat 2019 dazu das Buch „Automating the News“ veröffentlicht. Darin beschreibt er anhand vieler Beispiele im Groben vier Bereiche, in denen Automatisierung Journalisten und Medienhäusern helfen kann:

  • Geschwindigkeit: Automatisierung kann Daten in wenigen Sekunden in vordefinierte Text-Templates füllen und veröffentlichen,
  • Qualität: gerade Zahlen können ohne menschliches Zutun mit weniger Fehlern weiterverarbeitet werden – wenn die Input-Daten fehlerfrei sind,
  • Breite: Automatisierung kann mehr Bereiche abdecken, als das menschliche Journalisten leisten können,
  • und Personalisierung: mit Automatisierung können wir die Daten hervorheben, die die Nutzer persönlich betreffen.

(Ich habe mit Diakopolous ein Interview für die SZ geführt / Für das Nieman Lab hat er außerdem einen spannenden Post über das Thema geschrieben)

Die Überschneidung von Automatisierung und Journalismus hat ziemlich viele Facetten: Welche Datenquellen nehmen wir für die Automatisierung? Wie bringen wir den Computerprogrammen journalistische Grundsätze bei? Wie kontrollieren wir die Programme? Und wie machen wir kenntlich, dass nicht ein Mensch, sondern ein Skript einen Text verfasst hat?

Ich konzentriere mich in diesem Blogpost aber vor allem auf meine Erfahrungen aus der Praxis.

Automatisierung bei der SZ

Auch bei der SZ haben bisher vor allem Katharina Brunner und Martina Schories mit dem Thema Automatisierung experimentiert. Vom Datenjournalismus zur Automatisierung ist es auch kein sehr weiter Weg: Beide nutzen Daten, und bei beiden wird programmiert.

Im Projekt „Better Polls“ [hier auf Github] wurden Umfragen auf eine neue Art dargestellt – ohne absolute Werte, mit ihrem Fehlerbereich. So wie es inzwischen Medien auf der ganzen Welt machen: New York Times, FiveThirtyEight oder die BBC.

Screenshot SZ.de: Projekt Better Polls, Liniendiagramm mit aggregierten Umfragen zur Bundestagswahl 2017
Quelle: Screenshot SZ.de

Bei den Bundestagswahlen 2017 und den Landtagswahlen in Bayern 2018 hat die SZ zum ersten Mal auf mit automatisch erstellten Texten gearbeitet. Wobei „automatisch“ nicht heißt, dass davor nicht ziemlich viel Arbeitsaufwand in Entwicklung, Berechnung und Testen gesteckt worden wäre. Für jeden Wahlkreis haben die Datenjournalistinnen damals das Wahlergebnis einzeln, als eigener Artikel über ein Skript ausgespielt und mit vielen Vergleichsgrafiken angereichert.
[Ein Beispiel gibt es hier]

Automatisierung für die US-Wahlen 2020

Und auch jetzt, im Beginn des US-Wahlkampfes 2020 haben wir uns wieder gefragt, wie wir unseren Nutzerinnen und Nutzern aktuelle Grafiken bieten können – ohne die ständig händisch aktualisieren zu müssen.

Für die US-Vorwahlen nutzen amerikanische Medien Umfrage-Aggregatoren. Sie berechnen also aus allen einzelnen Umfragen einen Mittelwert. Der Gedanke dabei: Umfragen sind immer mit Ungenauigkeiten behaftet. Bildet man aus Umfragen aber den Durchschnitt, so gleichen sich die verschiedenen Abweichung nach Oben und Unten im Idealfall wieder aus. Auch wir haben uns daher für eine solche Aggregation entschieden. Wir nutzen dabei die Daten von FiveThirtyEight, das alle Umfrageergebnisse verfügbar macht, und alle amerikanischen Umfrageinstitute nach ihrer Leistung einstuft. Wir können daher nur die besten Instituten auswählen.

Die Berechnung für unseren Mittelwert machen wir (wie so oft) in der Programmiersprache R. Am Ende entstehen zwei Grafiken. Ein Scatterplot mit Liniendiagramm für die nationalen Umfragen über die Zeit hinweg…

Quelle: Screenshot SZ.de

… und eine Tabelle in Datawrapper, die die Umfragen in den Einzelstaaten der kommenden Vorwahlen aggregiert:

Screenshot SZ.de Datawrapper-Tabelle mit Umfragen in US-Einzelstaaten

Die Tabelle befülle ich über das DatawRappr-Package, das ich neulich veröffentlicht habe.

Jeden Morgen um 5.30 Uhr läuft ein Skript auf unserem Server und aktualisiert die Umfragen. So haben wir einen immer aktuellen Überblick über das demokratische Rennen in den USA. [Hier der Link auf den Überblicksartikel zu den Vorwahlen auf SZ.de]

Weiterführende Links zu Automatisierung im Journalismus:

Anmerkung: Ich habe bei den SZ-Beispielen nochmal präzisiert, wer die Projekte umgesetzt hat. War da ein bisschen zu pauschal.

Introducing DatawRappr

Datawrapper ist eines der erfolgreichsten Visualisierungstools für Journalisten. Mit einer neuen Erweiterung können die Daten aus R jetzt auch ohne Umwege in Datawrapper-Grafiken geladen werden.

Nein, dieser Blogpost soll keine Werbung für Datawrapper werden. Und der „Tippfehler“ im Titel ist gar keiner (na, wer hat sich gewundert?). Ich will in diesem Post kurz beschreiben, warum ich eine Bibliothek für die Statistiksoftware R geschrieben habe, die auf die Datawrapper-API zugreift. Und weil viele dieser R-Erweiterungen gerne mit dem Namen der Software spielen (ihr Vorgänger hieß übrigens S), wollte ich dem in nichts nachstehen: DatawRappr.

In vielen meiner Arbeitsstellen wurde Datawrapper eingesetzt. In meinem aktuellen Job visualisieren wir damit alle möglichen Grafiken auf der Homepage, oder erstellen damit schnelle Karten in Breaking-News-Situationen.

Inzwischen tauchen die Grafiken sogar schon in der gedruckten Zeitung auf:

https://twitter.com/Datawrapper/status/1175365864406822912

[/cookie]

In der Regel nutzen wir Datenjournalisten für unsere Auswertungen die Software R. Sie ist frei verfügbar und hat eine riesige Community, die für jeden Anwendungsfall eigene Erweiterungen geschrieben hat. (Vor allem aus der Informatik-Richtung kommt Python, die Sprache kann quasi dasselbe. Manche Leute mögen die eine, andere die andere mehr.)

[Mehr zu R habe ich in einem eigenen Blogpost aufgeschrieben.]

Um die Daten von R in Datawrapper zu bekommen, ist momentan noch ein Umweg nötig:

  • Entweder wir speichern die Ergebnisse für die Grafik als CSV und copy&pasten sie in Datawrapper (oder laden die CSV dort hoch)
  • Oder wir nutzen die Bibliothek clipr, die die Ergebnisse der Berechnungen in die Zwischenablage kopiert:

In einem aktuellen Projekt wollen wir aber automatisiert und regelmäßig Berechnungen durchführen (die Daten verändern sich ständig), und daraus Datawrapper-Grafiken generieren. Wir wollen aber ungern dauernd selbst daran denken müssen, die Grafiken zu aktualisieren. Außerdem müssen wir manchmal nicht nur die Daten, sondern auch die Beschreibungstexte ändern.

Die Datawrapper-API

Zum Glück hat Datawrapper dafür eine Lösung: Die API.

Über diese Schnittstelle können wir auf alle Funktionen zugreifen, die Datawrapper auch über sein Web-Interface anbietet. Gerade wurde die API von Version 1 auf Version 3 geupgradet. (Mehr dazu hat Datawrapper hier gebloggt)

Damit man direkt aus R darauf zugreifen kann, habe ich also die R-Erweiterung geschrieben. Mit ihr kann man zum Beispiel:

Was genau DatawRappr kann – und wie es genau funktioniert, steht in der Dokumentation. Zwar ist die Erweiterung schon in Version 1.0, aber vermutlich wäre 0.9 – also eher eine Beta-Version – angebrachter. Noch ist sie einfach zu wenig getestet, vor allem auf Windowssystemen. Aber: Sie geht! 😉

Infos zu DatawRappr

Der Code von DatawRappr steht auf Github. Es gibt eine eigene Dokumentation dazu.

Installiert wird es ganz einfach in R mit dem Package devtools:

Überstunden-Tracking mit R und IFTTT

Previewbild eines Balken-Diagrams mit meinen Überstunden

Der Europäische Gerichtshof will, dass Arbeitgeber die Arbeitszeit ihrer Mitarbeiter erfassen. Bis das eingeführt wird, behelfe ich mir selbst.

Ein Urteil aus Luxemburg hat die Arbeitgeber ziemlich durchgeschüttelt. Der Europäische Gerichtshof hat entschieden, dass Arbeitgeber die Arbeitszeiten von ihren Angestellten systematisch erfassen müssen. Für die Arbeitgeber das Ende der flexiblen Arbeitszeiten und der Vertrauensarbeitszeit. Für die Angestellten aber wohl die Chance auf mehr Gesundheit. Denn Überstunden machen krank, hat zumindest eine Studie der Unis Halle-Wittenberg und Erlangen-Nürnberg für Angestellte im öffentlichen Dienst herausgefunden.

Nicht nur deshalb, sondern vor allem, weil ich einen Überblick über meine Arbeitszeiten haben wollte, habe ich im Januar begonnen, zu tracken, wann ich meine Arbeit betrete, und wann ich sie verlasse. Das klappt gut, wenn man einen festen Ort hat, den man morgens betritt.

Mein Handy erkennt, wann ich die Arbeit betrete und verlasse

Ich nutze für mein Tracking IFTTT. Das steht für „If This Then That“ – eine Webseite, auf der die Nutzer verschiedene Webanwendungen zusammenbinden können. In meinem Fall benutze ich deren App auf meinem Handy mit einem sogenannten „Geo-Fencing“. Wie der Name andeutet, lege ich einen „umzäunten“ Bereich fest, durch den eine Aktion ausgelöst wird, wenn ich ihn betrete oder verlasse. In meinem Fall schreibt die App dann die Uhrzeit und entered oder exited in ein Google Spreadsheet.

So sieht das Google Spreadsheet mit den Rohdaten aus.

Diese Apps könnte man selbst entwickeln. Bei IFTTT ist die Infrastruktur aber schon vorhanden. Und andere Entwickler haben diese Schnittstellen schon gebaut. Ich konnte sie also ganz einfach wiederverwenden.

So sieht das Applet in IFTTT aus.

Von den Daten zur Auswertung

Die Daten laufen also seit Januar in das Spreadsheet ein. Doch ich wollte ja auch irgendwie davon profitieren, dass ich diese Daten erhebe. Meine Idee: Jeden Freitag bekomme ich eine Übersicht meiner Überstunden für die vergangene Woche per Mail geschickt.

Zunächst habe ich ein Auswertungsskript geschrieben. Dafür nutze ich diese Bibliotheken in R:

In meinem Workflow downloade ich die Daten aus dem Spreadsheet und arbeite dann mit ihnen weiter. Das geht ganz einfach mit einem Spreadsheet, das öffentlich gestellt wurde. Das kann man als CSV herunterladen: https://docs.google.com/spreadsheets/d/[ID zum Spreadsheet]/export?format=csv

In R wandle ich die computer-ungeeignete Datumsangabe in ein Format um, mit dem ich weiterrechnen kann. Außerdem berechne ich Wochentag und Kalenderwoche:

Und dann gibt’s’s auch schon erste Ergebnisse. Ich berechne für jeden Arbeitstag die Differenz zwischen den Soll- und Ist-Stunden. Weil ich 36,5 Stunden in der Woche arbeiten muss, komme ich auf 7,3 Stunden pro Tag (ohne Pausen). Das fasse ich dann nach KWs zusammen:

Das Ergebnis sieht in R so aus:

Die Wochenarbeitszeiten in R

Mit zwei Filterbefehlen kann ich aus diesen Daten schon ein bisschen Text für meine Mail generieren:

berechnet mir, wie viele Überstunden ich in der vergangenen Woche gemacht habe. Mit einem if_else bekomme ich dann eine Aussage, welches Vorzeichen dieser Wert hat – und kann daraus Worte generieren:

Das Ergebnis wird dann zu text_result zusammengebunden und ergibt den veränderbaren Text für meine Mail:

Damit das ganze anschaulicher wird, gebe ich außerdem noch zwei Grafiken aus.

Der E-Mailtext body_text selber ist eigentlich nur ein Zusammenfügen von Bruchstücken in HTML:

Mit der Bibliothek MailR verbinde ich mich dann mit meinem Mailaccount und schicke die Mail ab:

Das Ergebnis sieht dann auf dem Handy so aus:

Screenshot aus der Arbeitszeiten-Mail auf dem Handy

Wie sich das Grundgesetz in 70 Jahren verändert hat

Unsere Verfassung feiert runden Geburtstag – wie stark der Text seit 1949 umgeschrieben wurde, habe ich in einem Projekt recherchiert.

Rund 70 000 Zeichen hatte das Grundgesetz im Jahr 1949. Heute sind es deutlich mehr, denn in insgesamt 63 Änderungen wurde viel gestrichen und vor allem hinzugefügt.

In der SZ haben wir zum Verfassungsjubiläum eine Sonderbeilage gemacht. Darin war auch eine Seite voller Grafiken. Unsere Idee dafür: Können wir zeigen, wie sehr sich das Gesetz von heute und das Gesetz von damals unterscheiden?

Ein CCC-Projekt will das Grundgesetz versionieren

Ein bisschen Glück hatten wir in diesem Fall, denn die Daten waren schon zum großen Teil da. Ein Projekt des chaospott in Essen hat vor einigen Jahren versucht, das Grundgesetz versionierbar zu machen – also jede Änderung im Text nachvollziehbar zu speichern. Ähnlich wie Computercode (aus der Richtung kommen die chaospott-Leute auch).

Für das Projekt haben sie extra die Software DocPatch geschrieben (hier auf Github). Die sorgt dafür, dass aus den einzelnen Dateien, die jede Änderung im Text beschreiben (sogenannte Patches) am Ende wieder ein kompletter Text wird – und sogar in verschiedenen Ausgabeformaten ausgegeben werden kann (zum Beispiel in PDF, Word, Markdown, Plaintext).

Mit dem Versionskontrolltool quilt tracken die Leute vom chaospott jede Änderung, die eine neue Version des Grundgesetzes enthält. Und das kann auf einmal gleich mehrere Artikel betreffen. Sie spielen quasi jede Version einmal durch, damit quilt weiß, was es für eine bestimmte Version verändern muss.

Auf einem Githubrepository werden dann alle Versionen Patches gespeichert, die geben an, was vom ursprünglichen Text verändert werden muss, damit der jeweilige Text rauskommt. Der Vorteil: DocPatch kann ganz einfach auch andere Versionen als die aktuelle ausgeben.

So sieht ein solcher Patch aus:

Die Zeilen mit + und - geben jeweils an, welcher Text hinzugefügt oder entfernt werden soll. Der Ausschnitt bezieht sich auf 013.md – also Artikel 13. md ist der Dateiname für Markdown-Dateien. Die lassen sich sehr einfach in andere Dateiformate umwandeln.

Die Daten waren da – und dann?

Wir hatten also eine gute Datengrundlage für die jeweiligen Versionen des Grundgesetzes – aber wie konnten wir zwei Versionen vergleichen? Dafür habe ich die Software wdiff genutzt.

Anders als die Patches, die versuchen, möglichst große Bereiche zu finden, die sich unterscheiden, vergleicht wdiff auf einer Wort-zu-Wort-Basis. Ist ein Wort, oder nur ein Buchstabe anders, wird die Änderung ausgegeben. Der Vorteil: wdiff gibt den kompletten Text aus, markiert aber, was eingefügt und was gelöscht wurde. Hier am Beispiel einer kleinen Änderung in Artikel 1 Abs. 3:

In R mussten wir also nur noch für jeden Artikel die Zeichen zwischen [--] und {++} zählen – und kamen so auf die Gesetzesteile, die verändert wurden.

Der R-Code für diese Zählung sieht kompliziert aus. Aber hauptsächlich, weil man mit sogenanntem RegEx (Regular Expressions) die Texte zwischen den Klammern extrahieren muss. nchar() berechnet die Zahl der einzelnen Zeichen. Und aus denen kann man hinterher ganz einfach einen Anteil berechnen.

Das klingt eigentlich ganz einfach. Trotzdem hat das Projekt mehrere Wochen gedauert. Denn zuerst wollte ich jeweils den kompletten Grundgesetztext vergleichen. Das hat überhaupt nicht funktioniert, weil wdiff immer ein Problem damit hatte, wenn neue Artikel eingefügt wurden (also alles mit Kleinbuchstaben: 16a, etc.). Die Lösung war relativ einfach: Immer nur einzelne Artikel vergleichen. In quilt lassen sich diese neuen Artikel auch anlegen, sie werden aber bei der Ausgabe von früheren Versionen des Grundgesetzes nicht mit angezeigt, wenn sie damals noch nicht drinstanden. Ziemlich cooles Tool.

Das Ergebnis fand in der Zeitung auf einer Grafikseite statt – und kann sich sehen lassen, finde ich:

Durchs Internet surfen – mit einem Skript in R

Im Internet stehen so viele Informationen. Ein Paradies für Datenjournalisten, die große Mengen an Informationen automatisiert abfragen wollen. Manchmal ist es einfach, an sie heranzukommen, manchmal etwas schwieriger. Denn manche Webseiten laden ihre Daten nicht in den Quellcode – dort, wo die einfachen Lösungen zum sogenannten Webscraping (über Scraping mit Python habe ich schon mal gebloggt) ansetzen. Doch mit ein bisschen Aufwand, können Datenjournalisten auch Seiten abfragen, die ihre Inhalte nachladen oder über Skripte generieren. Der einfachste Anwendungsfall ist aber: Der Weiter-Button.

Neulich hatte ich einen Fall, in dem ich knapp 1500 Daten von Abgeordneten abrufen wollte. Sie waren über eine Suche zugänglich, wurden allerdings nur in Hunderterschritten angezeigt. Ich habe ein Skript geschrieben, dass die Suche startet, jede Seite aufruft, die Informationen speichert und nach allen Abgeordneten auf einer Seite den Weiter-Button drückt. Später kann ich dann jede einzelne Abgeordnetenseite herunterladen.

Zum Glück gibt es „Selenium“. Das ist ein Framework, das ursprünglich dafür entwickelte wurde, um Tests in Browsern zu automatisieren. Um also schnell testen zu können, ob Softwareupdates irgendein Problem für die Nutzer erzeugen. Selenium ahmt dafür das Verhalten eines Nutzers im Webbrowser nach. Es kann Felder ausfüllen, Buttons anwählen oder einen Mausklick simulieren.

Eigentlich basiert Selenium auf HTML und Javascript, für R gibt es aber (wie so oft, zum Glück) ein Package, das die Funktionen anbietet: RSelenium. Für die Extraktion der Informationen benutze ich rvest, eine weitere R-Bibliothek, die HTML-Code in R durchsuchbar macht.

RSelenium im Einsatz

RSelenium hat zwar eine gute Dokumentation, ich musste trotzdem viel rumprobieren, weswegen ich hier mal meine Vorgehensweise dokumentiere. Um rechtlich nicht angreifbar zu sein, habe ich den Namen der URL gelöscht.

Zunächst laden wir die beteiligten Bibliotheken. rvest und RSelenium erwähnte ich bereits, tidyverse ist eine Sammlung von mehreren R-Packages, die für die Arbeit mit Dataframes (also einer Tabelle) in R benutzt werden.

RSelenium startet auf einem lokalen Server und lädt dann ein neues Fenster in R. Darin wird ein Browser geöffnet, über den ich nachvollziehen kann was meine Befehle in R bewirken. remDr ist quasi der Browser, den ich steuere. Zum Beispiel lasse ich ihn einen Link öffnen – auf die erste Seite mit den Ergebnissen:

Insgesamt habe ich 14 Ergebnisseiten. Die habe ich händisch abgezählt für den Loop. Alternativ hätte ich auch eine Funktion schreiben können, die erkennt, wenn es keinen Weiter-Button mehr gibt.

14 Mal wiederholt R also den folgenden Vorgang: Es ruft eine Ergebnisseite auf, speichert dann den Link zur Detailseite jedes Abgeordneten, und klickt am Ende der Seite auf den Weiter-Button, den ich hier über seinen sogenannten X-Path finde. Dafür suche ich das Element auf der Seite, das den Text „nächste Treffer“ enthält. Und das ist nur der Weiter-Button.

Wir sind immer noch im Loop. Ich schreibe auf jeder Seite die Datenin Vektoren. Die Standardherangehensweise beim Webscraping ist allerdings: Detailseite öffnen und dann downloaden. Die Details kann ich dann auf meinem lokalen Rechner extrahieren, ohne unnötigen zusätzlichen Webtraffic bei der Seite zu erzeugen. Das werde ich auch hier tun. Ich sammle ja gerade die Links zu jeder Detailseite. Allerdings auch Namen und eine Information zu den Legislaturperioden der einzelnen Abgeordneten.

5 Sekunden lasse ich das Skript hier am Ende ruhen, damit ich nicht zu viel Last auf dem Server erzeuge. Das ist allerdings schon eine sehr lange Zeitspanne.

Während das Skript läuft, kann ich weiterarbeiten. Die R-Bibliothek BeepR spielt einen Sound ab, wenn alle Dateien heruntergeladen wurden. Dann verbinde ich die einzelnen Vektoren zu einem Dataframe in R, mit dem ich dann fortfahren kann. In meinem Fall loope ich jetzt über die einzelnen Links und lade die Dateien herunter. Das hätte ich aber natürlich auch schon im Schritt oben machen können. Ich habe mich aber dagegen entschieden, weil ich erstmal alle Links bekommen wollte, und mit denen dann weiterarbeiten kann.

Am Ende stoppe ich den Seleniumbrowser, der lokal auf meinem Rechner lief.

Fertig.

Shiny statt Javascript

R-ShinyApp Titelbild

Mit Javascript wird das Internet interaktiv. Das kann auch bei Datenanalysen wichtig sein. Mit „Shiny“ klappt sowas auch in R – ganz ohne Javascriptkenntnisse.

Mehr lesen

Durch die weitere Nutzung der Seite stimmst Du der Verwendung von Cookies zu. Weitere Informationen

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um das beste Surferlebnis zu ermöglichen. Wenn du diese Website ohne Änderung der Cookie-Einstellungen verwendest oder auf "Akzeptieren" klickst, erklärst du sich damit einverstanden.

Schließen