WebPlotDigitizer

Manchmal begegnet man im Web oder in Publikationen Diagrammen, deren Datengrundlage man gerne hätte, die aber nicht veröffentlicht ist. Um aus Visualisierungen zumindest annäherungsweise brauchbare Daten zu machen, gibt es den WebPlotDigitizer. Wer zum Beispiel wissen möchte, welche Daten hinter der Fernleihstatistik der Vanderbild-Library 1980-1985 stecken, schaut auf S. 9 von Interlibrary Loan in ARL Libraries, lädt den Screenshot in den WebPlotDigitizer und dann erhält man folgende Daten, die man auch gleich von dort in Plot.ly darstellen lassen kann.

1979,6489260399273; 9,939749839035454
1979,7446983769335; 10,10157323649587
1979,8404707139393; 10,302547455922518
1979,9362430509452; 10,558332826101887
1980,0276620999055; 10,842828799056495
1980,11472786082; 11,160080959722846
1980,193087045643; 11,511952942465792
1980,2322666380546; 11,79984889156434
1980,258386366329; 12,139591024404627
1980,2888593826492; 12,536754362795383
1980,3236856870149; 12,920758674914158
1980,3585119913807; 13,272463558910792
1980,3933382957466; 13,606224316172902
1980,4325178881581; 13,946444959059443
1980,4760507686153; 14,253648408754461
1980,5195836490725; 14,566593979004526
1980,56311652953; 14,911121212307352
1980,6153559860786; 15,243754053031864
1980,6763020187186; 15,56777371292381
1980,7416013394045; 15,88153958611031
1980,8112539481363; 16,200945041984802
1980,893966421005; 16,51317284716549
1980,9897387580108; 16,801583902316715
1981,081157806971; 17,0759006615601
1981,1725768559313; 17,30641200111461
1981,2683491929374; 17,46975793054038
1981,3641215299433; 17,567634985455953
1981,4598938669494; 17,656376848579406
1981,5589311699896; 17,749523179174062
1981,6514385409612; 17,841690739219565
1981,7472108779673; 17,94609293112951
1981,8429832149732; 18,0687655066237
1981,938755551979; 18,194048136915633
1982,0345278889852; 18,36862351638791
1982,130300225991; 18,601216685364427
1982,2260725629972; 18,838731671959557
1982,321844900003; 19,000555069419974
1982,417617237009; 19,145413110695028
1982,513389574015; 19,249815302604972
1982,609161911021; 19,332032028734055
1982,7049342480268; 19,414248754863138
1982,800706585033; 19,480805152205733
1982,8964789220388; 19,539531385155076
1982,9922512590447; 19,52421906367495
1983,0880235960508; 19,50168559058772
1983,1837959330567; 19,34769235752055
1983,2795682700628; 19,14280305589728
1983,3753406070687; 18,8974579049089
1983,4711129440745; 18,699093740280002
1983,5668852810807; 18,575116137386942
1983,6626576180865; 18,526830123628592
1983,7584299550924; 18,530745205825212
1983,8542022920985; 18,610351877156546
1983,9499746291044; 18,748684781437227
1984,037040390019; 19,034920790923664
1984,115399574842; 19,33797715355115
1984,1894054716195; 19,64262854966615
1984,2634113683966; 19,966420347631303
1984,3417705532197; 20,31254261442164
1984,4201297380428; 20,636334412386798
1984,5028422109117; 20,947525445800597
1984,594261259872; 21,253032359877082
1984,6900335968778; 21,52056297664632
1984,7858059338837; 21,73719752485946
1984,8815782708898; 21,883360593533386
1984,9773506078957; 21,994287922437703
1985,0731229449016; 22,056929237583674
1985,1688952819077; 22,084334812960034
1985,2472544667307; 22,10558811631313

Was ist ein Beeswarm-Plot?

Neben den Boxplots und Violinplots gibt es noch zahlreiche bis zahllose andere Visualisierungen. Kürzlich bin ich (wieder besten Dank an Holger) über Beeswarm-Plots [1] Aron Eklund 2015. beeswarm: The Bee Swarm Plot, an Alternative to Stripchart. URL: http://CRAN.R-project.org/package=beeswarm. gestolpert. Auch hiermit lassen sich Verteilungen darstellen.

# Pakete laden
library(ggplot2)
library(beeswarm)
 
# Daten aus CSV-Datei einlesen
apc

Das Skript wurde nun ein bißchen erweitert. Zuerst einmal musste ein weiteres Paket geladen werden, die Beeswarm-Library. Damit lassen sich Verteilungen sehr gut darstellen, sofern der Datensatz nicht allzu groß ist. Bei unserem Testdatensatz, den APCs der Uni Hannover, funktioniert das richtig gut:

Ergebnis:

Verteilung der APCs (Uni Hannover) nach Jahren
Verteilung der APCs (Uni Hannover) nach Jahren
Wie vorher, nur zusätzlich mit Boxplot
Wie vorher, nur zusätzlich mit Boxplot

Durch die Darstellung der einzelnen “Bienen” wird deutlich klarer, wie die Verteilung tatsächlich ist, da nicht nur ein ganzer Bereich für die jeweiligen Quartile abgesteckt wird. Die Menge der sinnvoll darzustellenden Punkte ist aber deutlich begrenzt. Versucht man, die Einwohnerzahlen von einigen Tausend Städten darzustellen, hat man im Ergebnis einen bunten Klecks, der letztendlich sehr stark einem unregelmäßig umrandeten Violinplot ähnelt.

Disclaimer: Dies ist eine äußerst laienhafte Erklärung!

References

References
1 Aron Eklund 2015. beeswarm: The Bee Swarm Plot, an Alternative to Stripchart. URL: http://CRAN.R-project.org/package=beeswarm.

Was ist ein Violin-Plot?

Der Violin-Plot (gibt es eine deutsche Bezeichnung? Violinen-Diagramm?) ist eine Weiterentwicklung des Boxplots. Er wurde 1998 vorgestellt [1]Hintze, Jerry L. & Nelson, Ray D. 1998. Violin Plots: A Box Plot-Density Trace Synergism. The American Statistician 52(2), 181–184. DOI: 10.1080/00031305.1998.10480559Besten Dank an Holger … Continue reading und soll die Visualisierung der Verteilungen verbessern. Das Boxplot-Skript kann man durch Ersetzung einer einzigen Funktion in ein Violinplot-Skript verwandeln:

# Pakete laden
library(ggplot2)
 
# Daten aus CSV-Datei einlesen
apc <- read.csv('https://raw.githubusercontent.com/OpenAPC/openapc-de/master/data/apc_de.csv',
         encoding = "UTF-8",
         sep=",", header = TRUE)
 
# Daten auswählen
apc <- apc[, c("Institution", "EURO", "Period")] # Nur noch drei Spalten
apc <- apc[apc$Institution == "Hannover U", ] # Nur noch Uni Hannover
 
# Boxplot erstellen 
box <- ggplot(apc, aes(x = Institution, y = EURO))
box <- box + geom_boxplot()
box # Ausgabe
 
# Violinen-Plot erstellen
vio <- ggplot(apc, aes(x = Institution, y = EURO))
vio <- vio + geom_violin()
vio # Ausgabe

Ich habe den Boxplot zur besseren Vergleichbarkeit im Skript belassen.

Ergebnis:

Beispiel für einen Violinplot
Beispiel für einen Violinplot

Aus der englischen Wikipedia:

The violin plot is similar to box plots, except that they also show the probability density of the data at different values (in the simplest case this could be a histogram). Typically violin plots will include a marker for the median of the data and a box indicating the interquartile range, as in standard box plots. Overlaid on this box plot is a kernel density estimation.

Dieses war der zweite Plot, und der nächste folgt sofott.

Disclaimer: Dies ist eine äußerst laienhafte Erklärung!

References

References
1 Hintze, Jerry L. & Nelson, Ray D. 1998. Violin Plots: A Box Plot-Density Trace Synergism. The American Statistician 52(2), 181–184. DOI: 10.1080/00031305.1998.10480559
Besten Dank an Holger für den Hinweis!

Was ist ein Boxplot?

Kürzlich fragte ich auf Twitter, ob man in bibliothekarischen Publikationen erklären müsse, was Boxplots sind, wenn man sie zur Visualisierung von Daten verwenden möchte. Tenor: Eher ja.

Eigentlich sind Boxplots nicht sonderlich kompliziert. Mit Boxplots kann man Verteilungen in Daten visualisieren. Nehmen wir – als einfaches und leicht nachzuvollziehendes Beispiel – die APCs (“Article processing charge”), die im Open-APC-Projekt gesammelt werden.

Die Beispiele hier sind mit R erstellt und relativ leicht nachvollziehbar. Einfach R (und unbedingt RStudio!) installieren und einfach ausprobieren. Es ist nicht so schwer, wie es zuerst aussieht. Und es gibt Unmengen an Tutorials und Büchern zu R. Und vor allem Stackoverflow.

Also: RStudio starten, die hier verwendeten Pakete installieren und dann folgendes Skript eingeben:

# Pakete laden
library(ggplot2)
 
# Daten aus CSV-Datei einlesen
apc <- read.csv('https://raw.githubusercontent.com/OpenAPC/openapc-de/master/data/apc_de.csv',
         encoding = "UTF-8",
         sep=",", header = TRUE)
 
# Daten auswählen
apc <- apc[, c("Institution", "EURO", "Period")] # Nur noch drei Spalten
apc <- apc[apc$Institution == "Hannover U", ] # Nur noch Uni Hannover
 
# Boxplot erstellen 
box <- ggplot(apc, aes(x = Institution, y = EURO))
box <- box + geom_boxplot()
box # Ausgabe

Der Boxplot sieht dann folgendermaßen aus:

Boxplot-Beispiel
Beispielboxplot mit den APCs der Universität Hannover

Erklärung:
X-Achse = Institution; Y-Achse = Höhe der APC in Euro. Was bedeutet jetzt dieses komische Kästchen mit den Strichen und Punkten? Ganz einfach:

Die Box entspricht dem Bereich, in dem die mittleren 50 % der Daten liegen. Sie wird also durch das obere und das untere Quartil begrenzt […]. Dieser ist ein Maß der Streuung der Daten, welches durch die Differenz des oberen und unteren Quartils bestimmt wird. Des Weiteren wird der Median als durchgehender Strich in der Box eingezeichnet. Dieser Strich teilt das gesamte Diagramm in zwei Hälften, in denen jeweils 50 % der Daten liegen.

Die “Antennen” (oder “Whisker”) auf und unter der Box stehen für die oberen und unteren 25 %. Ausreißer werden durch einzelne Punkte gekennzeichnet. In diesem Fall gibt es zwei Ausreißer zum unteren Ende.

Soviel erst einmal dazu. Es gibt noch viele andere Visualisierungsmöglichkeiten, von denen ich hier demnächst noch einige vorstellen möchte.

Disclaimer: Dies ist eine äußerst laienhafte Erklärung!

Ein Datensatz – 29 Ergebnisse, das ist nicht absurd

Wissenschaft absurd titelt Spiegel Online. Ein Datensatz – 29 Ergebnisse! Untersucht wurde ein Datensatz auf die Fragestellung, ob dunkelhäutige Fussballspieler häufiger rote Karten sehen als ihre Kollegen mit hellerer Hautfarbe. Dabei kam es zu einigermaßen unterschiedlichen Ergebnissen. Was auch nicht verwunderlich und aus vielen Disziplinen bekannt ist.

“Das Ergebnis jedes Teams ist stark beeinflusst von subjektiven Entscheidungen während der Datenanalyse”, konstatieren Silberzahn und Uhlmann. Wenn nur eine der Arbeiten als Studie publiziert worden wäre, hätte man durchaus ein Ergebnis lesen können, das von anderen abweicht. “Das bedeutet, dass man eine einzelne Analyse nicht zu Ernst nehmen sollte”, mahnen die Forscher.

Und darum gibt es Meta-Analysen wie z.B. vom Cochrane Institute, deren Ergebnisse dann in einem sogenannten Forest Plot visualisiert werden können. Ein sehr gut lesbares Buch, in dem unter anderem dieses Thema besprochen wird, ist übrigens “Die Wissenschaftslüge” von Ben Goldacre. Ein dämlich klingender deutscher Titel, aber das Buch ist wirklich lesenswert. Florian Freistetter  hat den Inhalt in seinem Blog gut zusammengefasst.

Die komplette Studie gibt es hier.

[Besten Dank an Holger für den Hinweis!]

R-Einführung in c't und anderswo

Ich verweise hier seit ein paar Jahren immer mal wieder auf R. R ist (laut Wikipedia) eine freie Programmiersprache für statistisches Rechnen und statistische Grafiken. R sieht auf den ersten Blick ein wenig abschreckend aus. Aber es existieren sehr, sehr viele Tutorials und Einführungen für Ein- und Umsteiger mit jeden denkbaren Vorkenntnissen.

In der aktuellen c’t (Heft 3/2014, S. 182-187) wurde eine Artikelserie begonnen, in der Andreas Krause in R einführt. Zielgruppe sind Programmierer. Eine andere Einführung, die ich sehr empfehlen kann, ist als RRZN-Handbuch erschienen. Das RRZN heißt zwar jetzt LUIS, die Handbücher werden aber zumindest bis jetzt unter altem Namen vertrieben. Und auf Coursera hat kürzlich wieder der Kurs Computing for Data Analysis begonnen, in dem R-Grundlagen vermittelt werden.

Lizenzen per OAI-PMH abfragen

Wer herausfinden möchte, welche Lizenzen auf einem Repository verwendet werden, kann dafür das R-Paket OAIHarvester nutzen. Das folgende Skript ist vielleicht nicht elegant, aber es funktioniert zumindest bei OPUS3-Repositories.

library("OAIHarvester")

# Get OAI-Data. Three repositories to choose from. Just uncomment.
# baseurl <- "http://opus.bsz-bw.de/fhhv/oai2/oai2.php"
# baseurl <- "http://edoc.bbaw.de/oai2/oai2.php"
# baseurl <- "http://opus.kobv.de/euv/oai2/oai2.php"

x   <- oaih_harvest(baseurl,
             prefix = "oai_dc", from = NULL, until = NULL, set = NULL,
             transform = TRUE)

sets <- oaih_list_sets(baseurl)

x <- oaih_list_records(baseurl)
## Drop deleted records and extract the metadata.
m <- x[, "metadata"]
m <- oaih_transform(m[sapply(m, length) > 0L])

## Transform data to data.frame
o <- as.data.frame(m)

# Convert and table:
liccount <- as.character(as.vector(o$rights))
table(liccount)

Das OAIHarvester-Paket bietet noch deutlich mehr. Dies ist nur eine von vielen möglichen und nützlichen Anwendungen.