2012-01-10

Interaktive Graphiken online Präsentieren

Wieder einmal gibt es eine neue Ausgabe des R Journal und wieder finden sich dort spannende Themen. Besonders aufgefallen ist mir dieses mal ein Artikel von Markus Gesmann und Diego de Castillo: Using the Google Visualisation API with R!

 Mit dem googleVis Paket können interaktive Graphiken erstellt und direkt im Browser angezeigt werden.

Als kleiner Vorgeschmack:

Die Wechselkurse von EUR, GBP, YEN und Renminbi (Chinesische Währung) - jeweils zum USD.AnnotatedTimeLineIDf456e3929f

R version 2.14.1 (2011-12-22) • googleVis-0.2.13Google Terms of UseData Policy


Der Weg dahin ist gar nicht schwer. Zunächst müssen die Daten in die passende Form gebracht werden. Für obige Graphik heißt das:
  • eine Spalte für das Datum
  • eine Spalte für die numerischen Werte, die hier als Linie angezeigt werden (die Wechselkurse, die angezeigt werden sollen)
  • eine Spalte für die Unterteilung der numerischen Werte in verschiedene Kategorien (hier: die verschiedenen Währungen)
  • eine Spalte für die Titel der Annotationen (die sowohl in, wie auch neben der Grafik angezeigt werden)
  • eine Spalte für die Annotationen
Das sieht dann folgendermaßen aus:


Jetzt reichen zwei Befehle um die entsprechende Graphik zu erstellen und anzuzeigen:

lineChart = gvisAnnotatedTimeLine(exchange.data, 

            datevar="Datum", # Datumsvariable
            numvar="Kurs",  # numerische Werte
            idvar="Währung",  # enthält die Gruppen
            titlevar="Titel", # enthält die Titel der Bemerkungen
            annotationvar="Anmerkung", # die Bemerkungen
            options=list(displayAnnotations=TRUE,#Bemerkungen anzeigen
            scaleColumns='[0,1]', # 2-Y-Achsen (eine links eine rechts)
            scaleType='allmaximized'))

erzeugt HTML-Code, der alle zum Anzeigen der Grafik benötigten Informationen enthält. Um das Ergebnis zu sehen benutzt man:

plot(lineChart)

. Im Browser öffnet sich dann die oben angezeigte Grafik. Das Kommando:

lineChart

zeigt bei Bedarf den der Grafik zugrundeliegenden HTML-Code an. Dieser enthält unter anderem auch die Daten selber. Somit kann man die Grafik einfach im Internet veröffentlichen indem man den HTML-Code auf dem eigenen Web-Space hoch lädt. Oder man kopiert den HTML-Code in den eigenen Blog.

Literatur:

2011-10-13

Datenimport mal anders

Wer kennt es nicht. Man liest ein Paper und denkt sich: Diese Daten hätte ich jetzt auch gern. Sei es um die Ergebnisse noch einmal selber nachzurechnen oder andere Methoden mit der vorgestellten zu vergleichen.

[Einschub: Ok, es gibt wahrscheinlich den einen oder anderen, der diese Gefühl nicht kennt. Aber ganz abwegig ist es auch nicht :-)]

Glücklich, wer eine passende Grafik in dem Paper findet und das R-Paket digitize kennt.

Nehmen wir uns mal die folgende Grafik vor. Fehlen uns dazu die numerischen Werte (also die Koordinaten der einzelnen Punkte), so könnte man sich nun mit Lineal und Bleistift vor eine ausgedruckte Version setzen und die Werte der Punkte abmessen. Aber digitize macht es etwas bequemer.

Wir laden also das Paket digitize und müssen anschließend die Grafik in R importieren.

install.packages("digitize")
library(digitize)
axis = ReadAndCal("daten.jpg")


Es öffnet sich gleich die importierte JPG-Datei. Zuerst müssen wir nun 4 Referenzpunkte setzen. Jeweils 2 auf der X-Achse und 2 auf der Y-Achse. Das geschieht durch einen Linksklick in der Grafik.

Im nächsten Schritt müssen die einzelnen Datenpunkte in der Grafik markiert werden. Das geschieht wieder mit einem Linksklick in die Grafik.

points = DigitData(col="red")

Wer das ausprobiert, weiß spätestens jetzt warum sich das Paket nur für überschaubare Datensätze eignet. Manchmal dauert es etwas länger, aber wenn alle Punkte rot markiert sind beenden wir den Schritt indem man ESC drückt.
Zuletzt werden die gesammelten Achsen-Informationen benutzt um die Koordinaten der Punkte hochzurechnen. Dazu muss angeben werden an welchen Stellen die Punkte auf der X- bzw. Y-Achse gesetzt wurden (hier jeweils 0 und 2).

data = Calibrate(points, axis, 0, 2, 0, 2)

Es ergeben sich die Folgenden gerundeten Werte:

XY
1-2,5-2,6
21,21,3
300,3
40,80,4
522,2
60,10,3
7-0,3-0,3
82,32,8
9??
102,02,1


Abgesehen von minimalen Abweichungen stimmen diese Daten mit denen die ich tatsächlich benutzt habe um die Grafik zu erzeugen überein. Allein Punkt 9, der von den Koordinaten identisch zu Punkt 3 ist kann mit der Methode natürlich nicht gefunden werden. 2 direkt übereinanderliegende Punkte können in der Grafik schließlich nicht auseinandergehalten werden.

Literatur:
  • Timothée Poisot: The digitize Package: Extracting Numerical Data from Scatterplots - R Journal Vol 3/1 (June 2011). http://journal.r-project.org/archive/2011-1/RJournal_2011-1_Poisot.pdf (Stand:  10. Oktober 2011).


2011-10-07

(Welt)-Karten mit JMP

In Anlehnung an den letzten Beitrag möchte ich noch erwähnen, dass R natürlich nicht die einzige Software ist, die sich zum Erstellen von Karten eignet. Hier möchte ich noch kurz anhand der FIFA-Damen-Weltrangliste zeigen, wie sich die gleichen Grafiken in JMP erzeugen lassen.

Die benutzten Daten finden sich wieder im Internet.

Nachdem die Daten in JMP eingelesen sind erzeugen wir die Karte nun im Graph Builder (Graph ⇒ Graphik erstellen).

Zieht man die Ländernamen in den Shape- (bzw. Form-) Bereich des Graphbuilders entsteht automatische die entsprechende Weltkarte.
Danach fehlen noch die Farben gemäß der Punktezahl der verschiedenen Teams. Dazu zieht man die Variable Pts auf die Karte.
Nach einem bisschen Heraumspielen an den Farbverläufen (Rechtsklick auf die Legende ⇒ Verlauf) kann man eine Karte erzeugen, die der mit R erstellten verblüffend ähnlich sieht. Abgesehen davon, dass wir hier den Damen-Fußball und mit R den Herren-Fußball analysiert haben.
Auch hier stimmen die Namen der Länder nicht überall mit den von JMP erwarteten Namen überein. Das sieht man an den weißen Flächen auf der Karte (Zentral-Afrika, China,...).

Literatur:
  • FIFA Weltrangliste der Damen (Stand: 7. Oktober 2011) - http://www.fifa.com/worldranking/rankingtable/women/index.html

Weltkarten mit R

In der neuesten Ausgabe des R Journals findet sich ein lesenswerter Artikel zu dem Packet rworldmap. Diese erlaubt es mit wenigen Befehlen eine Weltkarte zu erstellen, in der die einzelnen Länder individuell eingefärbt sind. Wie einfach das ist will ich am Beispiel der FIFA-Männer-Fußball-Weltrangliste zeigen.

Länder eingefärbt nach ihren Punkten auf der Männer-FIFA-Weltrangliste
Zunächst müssen einige Pakete installiert werden. Wer sich mehr mit Landkarten in R beschäftigen möchte sollte einen Blick auf die Liste der mitinstallierten Pakete werfen: sp, maptools beschäftigen sich ebenfalls mit diesen Themen. 

install.packages("rworldmap")
library(rworldmap)

Nachdem die Bibliothek geladen ist müssen die Daten beschafft werden. Für unser Beispiel finden sich die Daten im Internet. Etwas aufbereitet sehen die Daten dann etwa so aus:

RankTeamPoints
1Spain1605
2Netherlands1571
3Germany1290
4Uruguay1184
5Portugal1158
6Italy1142


Wenn die Daten in R sind, brauchen wir nur noch 3 Befehle. Der erste verbindet die Information der Daten mit einer Weltkarte. Der zweite erstellt eine neue leere Weltkarte und der dritte benutzt die zuvor erzeugte Information um die leere Weltkarte einzufärben.

 
fifa.map.info = joinCountryData2Map(fifa.ranking, joinCode="NAME", nameJoinColumn="Team")

150 codes from your data successfully matched countries in the map
57 codes from your data failed to match with a country code in the map
96 codes from the map weren't represented in your data

Der Output sagt uns, dass 150 der Länder richtig erkannt wurden, 57 nicht erkannt wurden und 96 Länder in der Karte sind, die nicht von uns angesprochen wurden. Nicht erkennen kann R Länder die "falsch" geschrieben sind. So ist es natürlich ein Unterschied ob in den Daten USA (was bei uns der Fall ist) oder United States (was von R bzw. vom Packet rworldmap erwartet wird) steht. Im Moment wollen wir diese Problematik kurzfristig beiseite lassen und einfach die Karte zeichnen.

mapDevice()
mapCountryData(fifa.map.info, nameColumnToPlot="Points")
Die weißen Länder wurden nicht erkannt
Es ergibt sich die eingefärbte Karte mit einigen weißen Flecken. Dies sind Länder, die im ersten Schritt nicht erkannt wurden. Um diese Problem zu beheben müssen die Ländernamen im Datensatz an die Ländernamen, die das Packet kennt anpassen. Dabei hilft der Befehl

identifyCountries()

Mit Mausklick auf die Karte werden die unerkannten Ländernamen identifiziert. Diese können dann anschließend im Datensatz korrigiert werden.

Auf der Suche nach den richtigen Ländernamen
Nachdem die entsprechenden Ländernamen korrigiert wurden ergibt sich die endgültige Karte.
Mit korrigierten Ländernamen

Das Skript, dass die oberste Karte erzeugt verwendet noch einige zusätzliche Optionen. Der zugehörige Code findet im Anhang.


Literatur:
  • Andy South: rworldmap: A New R package for Mapping Global Data - The R Journal Volume 3/1, June 2011
  • Fifa Weltrangliste der Männer (Stand: 7. Oktober 2011) - http://www.fifa.com/worldranking/rankingtable/index.html

Anhang:

# Erstellen einer Karte mit der FIFA Weltrangliste
# Autor: Sebastian Hoffmeister - Statcon
# 7.10.2011

library(rworldmap) # Laden der benötigten Pakete
library(classInt)

fifa.ranking = read.csv(".../Fifa Ranking.csv") # Einlesen der Daten
fifa.map.info = joinCountryData2Map(fifa.ranking, joinCode="NAME", nameJoinColumn="Team") # Daten mit der Karte verbinden

palette = colorRampPalette(c("brown4", "darkgoldenrod1", "darkolivegreen4"))(80) # Farbverlauf selbst definieren.
classInt = classIntervals(fifa.map.info[["Points"]], n=80, style="jenks") # Eigene anzahl an Farb-Intervallen definieren
catMethod = classInt[["brks"]]

mapDevice() # Die leere Karte erstellen
mapCountryData(fifa.map.info, nameColumnToPlot="Points", colourPalette = palette, catMethod=catMethod) # Die leere Karte befüllen


2011-09-16

Interaktionen in Entscheidungsbäumen II

Im letzten Eintrag hatte ich schon mit relativ kleinen Beispielen gezeigt, dass die Berücksichtigung von Interaktionen in Entscheidungsbäume zweierlei Nutzen haben kann:

1. Der Baum wird kleiner und somit einfacher zu interpretieren.
2. Der Baum wird genauer und eignet sich somit auch besser für Prognosen.
(Natürlich gilt das nur, wenn die Interaktion relevant für die Erklärung der Zielgröße ist.)

An dieser Stelle möchte ich das noch an einem kurzem aber etwas komplexeren Beispiel verdeutlichen.


In dieser 3-dimensionalen Situation sind die zugrunde liegenden Interaktionen, die die Zielgröße (Cyan/Blau) beeinflussen, zu komplex um sie in einer geometrischen Form zu beschreiben. Ein einfacher Entscheidungsbaum versucht die Farbe der Punkte auf folgende Weise zu erklären:
Ohne ein Pruning durchgeführt zu haben ergibt sich ein Baum mit 12 Blättern und einer Missklassifikationsrate von 10%.

Im Vergleich dazu der Baum, der die Interaktion berücksichtigt:
Dieser Baum benutzt nur 3 Blätter um die (nicht verrauschten) Daten perfekt zu erklären.

Natürlich ist es nicht sonderlich verwunderlich, dass der Baum der die volle Information über das zugrundeliegende Problem hat besser ist als einer dem entscheidende Information fehlt. Interessant ist aber, dass die Berücksichtigung von Interaktionen in der Praxis bis dato keine Rolle spielt. Tatsächlich unterstützt weder R noch JMP die Verwendung von Interaktionen in Entscheidungsbäumen von sich aus. In beiden Fällen müssen die Wechselwirkungen zunächst händisch erzeugt werden bevor sie als Einflussgrößen angegeben werden können.

Anhang:

# Entscheidungsbäume und Interaktionen II
# Sebastian Hoffmeister - Statcon
library(tree)
x1 = rnorm(100, 0, 1)
x2 = rnorm(100, 0, 1)
x3 = rnorm(100, 0, 1)
interaction = x1*0.5*x2*3*x3 # Die wahre Interaktion
y =  rep(0, 100)
for(i in 1:100) { # Erzeugen der Zielgröße
    if(abs(interaction[i])<0.5) y[i] = 1
}

simple.tree = tree(as.factor(y) ~ x1 + x2 + x3) # Ein einfacher Baum
summary(simple.tree)
plot(simple.tree)
text(simple.tree)

int = x1*x2*x3 # Man kennt natürlich nicht die einzelnen Koeffizienten in der Interaktion
interaction.tree = tree(as.factor(y) ~ x1 +x2 + x3 + int)
summary(interaction.tree)
plot(interaction.tree)
text(interaction.tree)