Heatmap CH-Olympiateilnehmer

image00

Die von der Sportinformation veröffentlichte Liste aller Schweizer Olympiateilnehmer (gerade gelernt: Olympioniken wäre falsch, siehe wikipedia) enthält nebst Name und Sportart auch den Wohnort. Einmal aufbereitet, lässt sich daraus mit Google Fusion Tables eine Heatmap erstellen, indem die Geolokalisierung von Fusion Tables die Sportler anhand der Wohnorte auf einer Karte platziert. Daraus wird ersichtlich, dass die grösste Stadt der Schweiz und sowie das kleine Davos die grösste Anzahl Olympiateilnehmer stellen – dazu kommt, ebenfalls interessant – Zug (aber wohl nicht wegen der idealen Trainingsbedingungen). Das Wallis sowie die Regionen Waadt und Nordwestschweiz können hingegen als wintersportliche Einöde bezeichnet werden. Leider lässt sich die Heatmap nicht exportieren, respektive lediglich als Screenshot einbinden. Die Karte mit den einzelnen Athleten hingegen kann eingebunden werden.

Abstimmungen: Karte

Ziel der Übung: Eine automatisch erzeugte Karte der Schweiz, die in Echtzeit die Ergebnisse von Abstimmungen zeigt, wobei die Kantone ihrem Entscheid entsprechend eingefärbt werden. Die Abstimmungsresultate werden auf admin.ch publiziert, das von mir verwendete Beispiel hier. Diese Daten habe ich mit Scraperwiki eingelesen. Der Python-Quellcode lautet:

#!/usr/bin/env python
import scraperwiki
import requests
import lxml.html
html = requests.get("http://www.admin.ch/ch/d/pore/va/20130922/det572.html").content
dom = lxml.html.fromstring(html)
i = 1
for entry in dom.cssselect('table tr'):
 if i > 1:
 if i < 28:
 post = {
 'kanton': entry.cssselect('td')[0].text_content(),
 'ja': entry.cssselect('td')[1].text_content().replace("`",""),
 }
 print post
 scraperwiki.sqlite.save(unique_keys=['kanton'], data=post)
 i = i+1

Seit einem Relaunch bietet Scraperwiki einen automatisierten Export der Daten im JSON-Format an. Die Funktion versteckt sich unter dem Menupunkt „Query with SQL“ . Die von mir erzeugte Datendatei enthält zwei Felder: Kanton und Ja-Stimmen-Anteil und ist hier zu finden. Die SQL-Abfrage dazu lautet:

select ja, kanton from swdata order by kanton limit 30

Für die Schweizerkarte im SVG-Format habe ich mich bei Wikimedia bedient. In einem Text-Editor habe ich die Farben entfernt und die IDs der einzelnen Kantone angepasst sowie die einzelnen Text- und Pathelemente in die gleiche Reihenfolge wie beim obengenannten JSON-File gebracht. Die so bearbeitete Version gibt’s hier.

Die Script habe ich mit der Java-Script Library D3 geschrieben. Ein sehr gutes, 20-teiliges Videotutorial zu D3 bietet youtube-user d3Vienno.

Der D3-Code ist extrem dicht und kurz:

d3.json('https://premium.scraperwiki.com/dexzd4i/5f6e1b937dbd42e/sql/?q=select%20%0A%09ja%2C%0A%09kanton%0Afrom%20swdata%0Aorder%20by%20kanton%0Alimit%2030%0A', function(data){
 var color = d3.scale.linear()
 .domain([20, 49.99, 50, 80])
 .range(["#143d00", "#cde6c1", "#ffcece", "#660000"]);

 d3.selectAll("path")
 .data(data)
 .attr("fill", function(d){ return color(d.ja)});
d3.selectAll("text")
 .data(data)
 .text(function(d){ return d.ja});
});

Zunächst wird das JSON-File importiert und als data-Array an eine Funktion weitergegeben. Dann wird eine Variabel „color“ definiert. Die Domain-Werte sind prozentuale Stimmanteile, es sind vier Werte, damit zwischen 49% und 51% auf der Karte klar zwischen hellrot und hellgrün unterscheidet werden kann. Die Range-Angaben sind die entsprechenden Farbcodes, wobei D3 den genauen Farbverlauf mittels der scale-Funktion automatisch regelt.

Dann folgen zwei Befehle, zunächst für die Kantonsflächen / Farbgebung, dann für die Angabe der Ja-Stimmen in Prozent. Der Quellcode des Scripts ist zu finden unter: http://jsfiddle.net/shufschmid/z28SL/3/

Bü Bü Bündnerfleisch mit soundbite

Wie gut Audio und Text zusammen passen, zeigt dieser von mir mittels soundbite angereicherte Artikel aus der Neuen Luzerner Zeitung:

Ein Bundesrat hat sehr wohl was zu lachen, selbst wenn er Hans-Rudolf Merz heisst. Das exerzierte der Finanzminister gestern in der Fragestunde des Nationalrats eindrücklich vor: Mit Tränen in den Augen krümmte er sich vor Heiterkeit, prustete immer wieder los und brachte kaum ein Wort heraus.

Die gute Laune ausgelöst hatte eine Frage des Waadtländer SVP-Bauern Jean-Pierre Grin. Dieser erkundigte sich danach, ob die Zollverwaltung auch genug gegen die Importzunahme von gewürztem Fleisch unternehme.

Anfangs gelang es dem obersten Chef der Zollbeamten noch, die einschlägigen Bestimmungen mit dem nötigen Ernst zu verlesen – etwa, dass es sich um «die Zolltarifnummer 1602.5099 (Schlüssel 914)» handle. Doch je verwirrender die Paragrafen und ihre Anwendung wurden, desto mehr verlor er die Contenance. Bis ihm die «sogenannten schweizerischen Erläuterungen zum Zolltarif» die Tränen in die Augen trieben. Und Merz mehrmals Anlauf nehmen musste, um den Ausdruck «Bündnerfleisch» am Stück und allgemein verständlich auszusprechen.

Vom Nationalrat erntete der bisweilen selber Belächelte spontanen Beifall. Auch politische Gegner lachten mit, als Merz Grin am Ende um Verzeihung bat und bekannte: «Ich habe bisweilen einfach nicht verstanden, was ich Ihnen vorlas.»

Einzelne Audiofiles per Soundbite einzubinden ist simpel und funktioniert dank HTML5 sowohl in modernen Browsern als auch auf mobilen Geräten*. Der Code dazu lautet:

 <span data-audio="audio/merz03.ogg">«Bündnerfleisch»</span>

Das grösste Problem war, die Javascript-Library in WordPress einzubinden. Die Anleitung dazu gibt’s hier.

Eingefügt habe ich in header.php:

<script type="text/javascript" src="/scripts/Soundbite.js"></script>

in footer.php

<link rel='stylesheet' href='scripts/Soundbite.css'>
<script> 
Soundbite.init();
 </script>

*Aus einem mir unbekannten Grund musste ich die Zeile 54 der Datei Soundbite.css (overflow: hidden;) entfernen, weil dieser Eintrag eine falsche Darstellung erzeugte. Bei mobilen Geräten besteht dieser Fehler weiterhin – Lösungsvorschläge gerne an shufschmid[(a)]gmail.com. Und nun noch als Bonus das Video in voller Länge:

Update: Zwillingsgeburten


Die JavaScript-Bibliothek „D3“ bietet unzählige Möglichkeiten, Daten im Web graphisch darzustellen. Als Einstieg kann ich das Tutorial von Scott Murray empfehlen. Allerdings sind gewisse JavaScript-Vorkenntnisse nötig, um das Tutorial zu begreifen. Nach dem Durcharbeiten der 13 Tutorial-Kapitel ist es mir gelungen, diese relativ simple Darstellung der Zwillingsgeburten im Kanton Basel-Stadt zu erstellen. Die Datengrundlage liefert das Statistische Amt, die ich in Excel in ein JavaScript-Array umgewandelt habe. Die Syntax von D3 ist äusserst knapp gehalten und ermöglicht daher ziemlich effektives Arbeiten. Der untenstehende Befehl beispielsweise erstellt für jeden Eintrag im Array „dataset“ einen Balken in der korrekten Höhe und Position.

 

svg.selectAll("rect")
 .data(dataset)
 .enter()
 .append("rect")
 .attr("x", function(d, i) { return i * (w / dataset.length); })
 .attr("y", function(d) { return h - yScale(d); })
 .attr("width", Math.round(w / dataset.length - barPadding))
 .attr("height", function(d) { return yScale(d); })

Genauere Erläuterungen sind dem Tutorial von Scot Murray zu entnehmen. Das einzige, was ich in Abweichung zum Tutorial selbständig hinzugefügt habe, sind die Jahreszahlen. Diese sind als .append(„text“)-Elemente hinzugefügt, müssen aber im svg.selectAll-Befehl einen neuen Namen erhalten, in meinem Beispiel svg.selectAll(„text2“).

Update: Daten via Google Drive, E-Book

Um D3 besser zu verstehen, habe ich mir das E-Book „Getting Started with D3“ heruntergeladen und mein erstes Beispiel neu programmiert. Zudem war es mir wichtig, einen Weg zu finden, wie ich die Daten als Google Spreadsheet speichern und ins Script einbinden konnte. Das entsprechende Datenfile findet sich hier. Der zunächst einfachste Weg schien mir, die Daten im JSON-Format zu übertragen, da D3 dieses Format unterstütz. Zum Export fand ich auch ein gutes Tutorial, das jedoch nicht zufriedenstellend funktioniert hat. Also habe ich auf CSV-Format umgesattelt, das von Google Drive direkt unterstützt wird (die entsprechende Anleitung ist im JSON-Tutorial enthalten) und bemerkt, dass D3 CSV-Import ebenfalls unterstützt. Die Import-Funktion lautet:

d3.csv('https://docs.google.com/spreadsheet/pub?key=0AnPrU5riz1tMdC10Nl9NOUxvVVc0YzBvSmJVOGNURHc&single=true&gid=0&output=csv', function(data){
 draw(data);
})

Im erwähnten E-Book wird die funktion draw(data) zur Ausgabe der Darstellung verwendet, die unabhängig von der Erstellung des Daten-Array funktioniert. Entsprechend habe ich mir beim Umprogrammieren meines Scripts an die Anweisungen aus dem E-Book gehalten. Programmiert habe ich auf jsfiddle.net, einer Online-Programmierumgebung für JavaScript, die auch die D3-Library direkt einbinden kann. Ebenfalls praktisch: Das Programm kann als iframe exportiert und beispielsweise hier in diesem Blog eingebunden werden (fürs Diagramm auf Result klicken).

Fortsetzung folgt.

Twitter im Bundeshaus

Twitter-User @polittweets führt eine aktuelle Liste twitternder National- und Ständeräte. Mit Hilfe des Excel-Tools NodeXL lassen automatisch auslesen und analysieren. Wegen der neuen restriktiven Richtlinien der Twitter-API dauert Follower-Abfrage der aktuell 84 auf der Liste eingetragenen Parlamentarier mehrere Stunden. Wichtig: Der Computer darf dabei einfach nicht in den Standby-Modus wechseln. Eine praktische Anleitung im Umgang mit Twitter-Listen und NodeXL liefert connectedaction.net. Das Resultat der Abfrage sind sämtliche „followed“-Verbindungen, das heisst Twitter User X folgt Twitter User Y. Falls Y User X ebenfalls folgt, ergibt das eine zweite Verbindung. Die Daten können mittels NodeXL weiterverarbeitet oder in die Visualisierungs-Software Gephi importiert werden. Für mein Beispiel „Twitterkönige im Bundeshaus“ habe ich Google Fusion Tables verwendet. Dazu habe ich die Daten aus Excel per copy/paste in ein Google Spreadsheet eingefügt und daraus eine Fusion Tables Datei erzeugt. Um die am besten vernetzten Parlamentarier zu finden, habe ich in der Diagramm-Ansicht einen Filter auf die erste Datenspalte angewendet. Durch einen Klick auf „sort by count“ zeigt es die Parlamentarier, die von anderen Parlamentarier am häufigsten gefolgt werden. Aktuell (28. Juli 2013) sind das Kathy Riklin (@kathyriklin) und Christian Wasserfallen (@cwasi). Beide zählen 70 der 84 twitternden Parlamentarier zu ihren Followern, allerding – wie der Network-Graph zeigt.

Interessen Grossräte

Die aktuellen Interessenbindungen der Grossräte werden auf bs.ch publiziert. Im Gegensatz zur PDF-Datei werden die Daten in den einzelnen Porträts ständig aktualisiert. Mittels Scraper-Wiki können die einzelnen Porträts automatisch ausgelesen werden, das entsprechende Python-Script ist hier. Das Script liefert ein Tabellen-File für sämtliche Grossräte in folgendem Format:

AticiMustafa InteressenbindungenArbeitgeberAD Atici Management GmbH, Basel (Gastronomie)Mitgliedschaften in F&uumlhrungs- und AufsichtsgremienA Foodliner GmbH, Basel (Gesellschafter/Geschäftsführer) AD Atici Management GmbH, Basel (Gesellschafter/Geschäftsführer)fabe: Familien-, Paar- und Erziehungsberatung, Basel (A/M)Neue Helvetische Gesellschaft Region Basel (A/M)MUSUB: Multikulturelle Suchtberatungsstelle beider Basel (A/M)GGG Ausländerberatung, Kommission (M)
SolandTanja InteressenbindungenArbeitgeberAids-Hilfe beider Basel, BaselMitgliedschaften in F&uumlhrungs- und AufsichtsgremienFDP Basel-Stadt (P)Hausbesitzerverein Basel, Delegiertenversammlung (M)Verein Gemeinnützige Institutionen, Basel (P)Rockförderverein Basel (A/M)Mitgliedschaften in staatlichen, nicht durch den Grossen Rat gewählten KommissionenNationalrat (M)Sicherheitskommission NR (M)

Die von Google Fusion Tables für Network-Graph vorgesehene Datenstruktur ist jedoch deutlich anders. Sie besteht im vorliegenden Beispiel aus einzelnen Verknüpfungen zwischen Organisationen und Grossräten. Das entsprechende Google Drive Spreadsheet steht hier zur Verfügung. Der Umwandlungsprozess war kompliziert und erforderte viel Handarbeit. Das beste Ergebnis erzielte ich durch den Einsatz von Excel und einem einfachen Text-Editor.

Die Tabelle kann danach in Google Fusion Tables importiert werden. Eine Filterung nach all jenen Organisationen, die mehr als einen Vertreter haben, lässt sich einfach vornehmen. Fusion Tables ermöglicht es, die einzelnen Werte nach Anzahl Nennungen anzuzeigen. Danach können die mehrfach vorkommenden Organisationen ausgewählt werden. Eine weitere Option ermöglicht es, die Werte aus den beiden Spalten unterschiedlich einzufärben.

Abstimmung Landrat

Eine Auswertung der ÖV-Abstimmung im Landrat im Rahmen des Sparpakets. Die Resultate sämtlicher Landratsentscheide, aufgeschlüsselt nach einzelnen Landräten, sind seit 2009 unter bl.ch verfügbar. Kombiniert man diese Daten mit den Wohnadressen der Landräte, kann man die Resultate via Google Fusion Tables auf einer Google Map darstellen. Zur Auswahl der einzelnen Symbole (im Beispiel: $ für Sparer, Bus-Symbol für ÖV-Förderer) muss man in Fution Tables „Nein“ durch den Namen des Symbols ersetzen. Eine praktische Übersicht sämtlicher verfügbarer Symbole gibt es hier: https://www.google.com/fusiontables/DataSource?dsrcid=308519#map:id=3.

Dasselbe gilt übrigens auch für Abstimmungen im Grossen Rat, hier ebenfalls ein Beispiel (Sperrung der Mittlere Brücke für Individualverkehr):

Babynamen Bethesda-Spital

Basierend auf denselben Daten der Baby-Galerie des Basler Bethesda-Spitals, ausgelesen mit ScraperWiki (beschrieben in diesem Blogpost), habe ich die Namen der Neugeborenen mit Hilfe mehrerer Wordcloud-Generatoren ausgewertet. Die einzelnen Anbieter haben Vor- und Nachteile, die perfekte Lösung habe ich bisher nicht gefunden. Unbrauchbar war der weitverbreitete Generator von wordle.net, vor allem weil der Export nur als Java-Applet funktioniert und es keine Möglichkeit gibt, das Resultat in einen Blog einzubauen. Besser gefallen hat mir der Wordcloud-Generator Tagxedo. Dieser erlaubt das Exportieren in viele verschiedene Formate. Damit die Wordcloud interaktiv bleibt, wird jedoch das Microsoft Silverlight plugin benötigt. Am besten gefallen hat mir die Lösung von tagul.com. Auch bei diesem Generator können die Clouds in diversen Formaten exportiert werden. Die interaktive Lösung basiert auf Adobe Flash, die einzelnen Einträge können jedoch automatisiert verlinkt werden (in meinem Fall auf die Einträge des Entsprechenden Namens in der ursprünglichen Baby-Galerie).

Word Cloud mit tagul.com:

Die Interaktiven Versionen der anderen Generatoren sind:
Babynamen-Wordcloud auf Tagxedo.com
Babynamen-Wordcloud auf Wordle.net

Babygalerie Bethesda-Spital

ScraperWiki ist ein Werkzeug, um Daten aus Internetseiten zu extrahieren und analysieren. Mit Hilfe dieses Werkzeugs und einigen Zeilen PHP-Code habe ich die Baby-Galerie des Basler Bethesda-Spitals ausgelesen. Knapp 5000 Neugeborene werden in der Galerie aufgelistet, mit Name, Grösse, Alter, Geschlecht und genauer Geburtszeit. Die erhaltenen Daten habe ich mit Microsoft Excel weiter analysiert, beispielsweise die Geburtszeit daraufhin überprüft, ob sie innerhalb der „normalen Arbeitszeiten“ von Montag – Freitag zwischen 06:00 und 22:00 liegen oder ausserhalb. Danach habe ich das Excel-File in Google Fusion Tables importiert und damit folgende Visualisierungen erstellt:

Das Verhältnis sollte eigentlich genau 50:50 sein, da Babies normalverteilt geboren werden und die  Zeiten der beiden Kategorien (rot: Mo bis Fr, zw. 06:00 und 22:00) und (blau: Wochenende, Nacht) gleich viele Stunden beinhalten. Die Recherche könnte der Frage nachgehen, weshalb das so ist und ob dies in allen Spitälern so ist.

 

Bevölkerungsdichte Basler Quartiere

MIt Google Fusion Tables lassen sich schöne datenjournalistische Projekte verwirklichen und als Google Map optisch aufbereiten. Eine gute Einführung bietet das Tutorial: Grenzen, Gebiete und Daten mit Fusion Tables kartieren„. Die Tücken liegen jedoch im Detail: Zunächst müssen die Quartiergrenzen in Fusion Tables importiert werden. Die entsprechenden Files sind im Geoshop von bs.ch frei verfügbar, liegen jedoch in der nicht kompatiblen Projektionsverfahren vor. Das Bundesamt für Topographie bietet die notwendigen Tools, um Datensätze im Schweizer Projektionsverfahren auf das Projektionsverfahren von Google Maps umzurechnen. Am besten funktioniert hat der KML-Generator, der die Quartiergrenzen zugleich in ein von Google Maps lesbares Format überträgt. Nun können die Daten in Fusion Tables eingelesen und als Karte dargestellt werden. Noch eine letzte Anpassung der Daten ist nötig, bevor die Quartiergrenzen mit anderen Daten kombiniert werden können: Mittels eines einfachen Tricks müssen die Grenzen in Flächen umgewandelt werden. Dazu müssen die einzelnen KML-Tags folgendermassen ersetzt werden:

<LineString> --> <Polygon><outerBoundaryIs><LinearRing>
</LineString> --> </Polygon></outerBoundaryIs></LinearRing>

Nun können die Quartierflächen wie im oben erwähnten Tutorial mit beliebigen Datensätzen kombiniert werden. Viele entsprechende Daten mit Angaben zu den einzelnen Quartieren finden sich auf statistik-bs.ch/tabellen. Ein einfaches Beispiel ist die Bevölkerungsdichte in den verschiedenen Quartieren: