Deprecated: Function create_function() is deprecated in /customers/d/c/f/dominikschauer.com/httpd.www/wp-includes/pomo/translations.php on line 208 Blog – Dominik Schauer

How to create an R package (including documentation, vignettes and a manual)

 

Recently I created my first R package. While doing this I realized that there is no resource that covers in just one article:

  • how to create an package from scratch
  • add function documentation
  • add a vignette
  • and a reference manual

So this is exactly what I cover in this post. Don’t get me wrong, There are lots of great resources. Namely these are those that I used:

To create your first R package you will need two packages, “devtools” and “roxygen”.

install.package("devtools")
install.package("roxygen2")
library(devtools)
library(roxygen2)

1) Creating a package body

After installing these, you can create a frame for the contents of your package by calling

setwd("your/package/directory")
devtools::create("yourpackagename")

This will create a folder called “yourpackagename” in the directory “your/package/directory”. This folder will contain:

  • a sub-folder called “R”
  • a file called .gitignore
  • a file called .Rbuildignore
  • a file called DESCRIPTION
  • a file called NAMESPACE
  • an R project called “yourpackagename”

blogpost1

You can achieve a similar result by calling the function “package.skeleton()” from the package “utils” but here I won’t go into this.

2) Adding Functions

This will most likely take the most time. At the same time it is also not really related to the documentary work that is the topic of this post. The core purpose of your package is to execute R functions. To give your package this ability you need to write R files containing these functions and to place them inside the sub-folder /yourpackagename/R. Here is an example I copied from Fong Chun Chan’s Blog:

load_mat <- function(infile){   
  in.dt <- data.table::fread(infile, header = TRUE)
  in.dt <- in.dt[!duplicated(in.dt[, 1]), ]
  in.mat <- as.matrix(in.dt[, -1, with = FALSE])
  rownames(in.mat) <- unlist(in.dt[, 1, with = FALSE])  
  in.mat 
}

Save this as a load_mat.R to your R directory. For demonstration purposes I will keep it to just one file and one function but you can include multiple R files and each R file can contain multiple R functions. So for example your file could also look like this:

load_mat <- function(infile){   
  in.dt <- data.table::fread(infile, header = TRUE)
  in.dt <- in.dt[!duplicated(in.dt[, 1]), ]
  in.mat <- as.matrix(in.dt[, -1, with = FALSE])
  rownames(in.mat) <- unlist(in.dt[, 1, with = FALSE])  
  in.mat 
}

load_mat2 <- funciton(infile) {
  ...
}

In general, try to group together related functions into the same .R file (e.g. if you have a bunch of loading functions then putting them in R/load.R would be a good idea). One important thing to note here, is you need to add the @export tag above your function to indicate this function to be “exposed” to users to use. For example:

#' @export
load_mat <- function(infile){   
  in.dt <- data.table::fread(infile, header = TRUE)
  in.dt <- in.dt[!duplicated(in.dt[, 1]), ]
  in.mat <- as.matrix(in.dt[, -1, with = FALSE])
  rownames(in.mat) <- unlist(in.dt[, 1, with = FALSE])  
  in.mat 
}

The #' @export syntax is actually an Roxygen tag which we will discuss in Section 3. By doing this, this ensures that the load_mat() function gets added to the NAMESPACE (when you run devtools::document()) to indicate that it needs to be exposed. In case you wonder what the NAMESPACE is, you don’t need to worry about it at this point. We will discuss this in Section 5.

blogpost3

3) Documenting Functions

This always seemed like the most intimidating step to me. I’m here to tell you — it’s super quick. The package roxygen2 that makes everything amazing and simple. The way it works is that you add special comments to the beginning of each function, that will later be compiled into the correct format for package documentation. The details can be found in the roxygen2 documentation — I will just provide an example for our load_mat() function.

3.1 Writing the Documentation

So how do you get that nice documentation in R when I go ?load_mat. We can leverage off the roxygen2 which provides a very simple way of documenting our functions and then produces man/load_mat.Rd files which is what we see when we go ?load_mat. Both Hilary (Step 3: Add documentation) and Hadley (Object documentation) discuss this at length and I refer you to there pages.

#' Load a Matrix
#'
#' This function loads a file as a matrix. It assumes that the first column
#' contains the rownames and the subsequent columns are the sample identifiers.
#' Any rows with duplicated row names will be dropped with the first one being
#' kepted.
#'
#' @param infile Path to the input file
#' @return A matrix of the infile
#' @export
load_mat <- function(infile){   
  in.dt <- data.table::fread(infile, header = TRUE)
  in.dt <- in.dt[!duplicated(in.dt[, 1]), ]
  in.mat <- as.matrix(in.dt[, -1, with = FALSE])
  rownames(in.mat) <- unlist(in.dt[, 1, with = FALSE])  
  in.mat 
}

3.2 Processing the Documentation

Once you’ve got your documentation completed, you can simply run:

devtools::document()

This will generate the load_mat.Rd file from your annotations and put them in the automatically created yourpackagename/man folder  :

% Generated by roxygen2 (4.1.0): do not edit by hand
% Please edit documentation in R/load.R
\name{load_mat}
\alias{load_mat}
\title{Load a Matrix}
\usage{
load_mat(infile)
}
\arguments{
\item{infile}{Path to the input file}
}
\value{
A matrix of the infile
}
\description{
This function loads a file as a matrix. It assumes that the first column
contains the rownames and the subsequent columns are the sample identifiers.
Any rows with duplicated row names will be dropped with the first one being
kepted.
}

You will get one .Rd file for each function in your R package. Executing the document()  function also updates the NAMESPACE file in the main directory.

blogpost4

4) Installing your package (Bonus)

Go to the directory that contains the package and run.

setwd("..")
devtools::install("yourpackagename")

Now it is as simple as installing the package! You need to run this from the parent working directory that contains the yourpackagename folder.

Now you have a real, live, functioning R package. For example, try typing ?load_mat. You should see the standard help page pop up!

blogpost10

4) Creating Vignettes

Vignettes are extremely important to give people a high-level understanding of what your R package can do. To get started with generating a vignette, you can use the devtools::use_vignette() function for this. For instance,

devtools::use_vignette("introduction")

This will create a vignette/introduction.Rmd file. This is a vignette template Rmarkdown file that you can then use to fill out steps on how you can use your package. It doesn’t use the comments you have written earlier or any other information of your package. This function just gives you a template for the Vignette but you still have to write the Vignette yourself.

In case you are using R Studio executing this function will automatically open the introduction.Rmd. Clicking on “Knit” will then parse the Rmarkdown file and create an HTML page in the same format and also put it into the yourpackagename/man folder.

You can also create a PDF version of your Vignette. To do this you simply have to change a single line in the Rmarkdown file. Just replace

output: rmarkdown::html_vignette

with

output: rmarkdown::pdf_document

and click again on “Knit”.

blogpost6

5) Editing the DESCRIPTION

The DESCRIPTION file is used in two different places, in your automatically generated manual and on the CRAN package page (in case it gets published on CRAN). You can read about the DESCRIPTION file in detail here and I strongly suggest that you do so. The most important bits are the following. The file is basically a text file that defines some parameters which represent meta information about the package, such as the author, the required packages, the publishing date and more. “Devtools” manages some of these for you but the following parameters need to be adjusted manually. Follow the link above to see what can and what needs to be done.

6) Creating a PDF reference manual

As mentioned above, the DESCRIPTION file is used to create the PDF manual. And once again creating the file itself is the easy part. By writing the function documentation and editing the DESCRIPTION you already prepared everything and just need to run a single command:

setwd("your/path/yourpackagename")
system("R CMD Rd2pdf . --title=Package yourpackagename --output=./manual.pdf --force --no-clean --internals")

This ensures your working directory is the main folder of the package, e.g. /yourpackagename/. It will create a file named manual.pdf in the main folder.

blogpost7

Internally, R creates a Latex document and related files first to generate the PDF. These intermediate files are usually deleted, but you may want to manually change something. Including --no-clean in the command skips the deletion. You will also find a folder named .Rd2pdfxxxxx in your main directory. This folder contains the same PDF but with another name (Rd2.pdf) and more importantly, the file Rd2.tex.

blogpost8

You can then open this file in your preferred Latex editor. In my case that is TexMaker. When you just open the file and try to compile it, you will get an error message telling you that “Rd.sty” is missing. The Rd.sty comes with base R since it is needed for the creation of package documentation. Its location depends on the OS you are using. The standard install path is R_HOME/share/texmf. You just need to go this derictory and copy the file into your yourpackagename/.Rd2pdfxxxxx folder. Now you can edit the Rd2.tex file and compile it to a custom PDF reference manual.

blogpost9

7) Making the package a GitHub repository (Bonus)

At this point, you already did what the preface of the post promised! You may want to to additionally put your package on GitHub for others to access it. This is not a post about learning to use git and GitHub though. For that I recommend Karl Broman’s Git/GitHub Guide. The benefit, however, to putting your package onto GitHub is that you can use the devtools install_github() function to install your new package directly from the GitHub page. For example I you might run

devtools::install_github("yourgithubusername/yourpackagename")

8) Do you have an R file I can download?

I do. Here it is.

Wie man eine Frage stellt

Dieser Beitrag wurde von zwei Büchern inspiriert, die ich während der letzten paar Tage gelesen habe  The Elements of Data Analytic Style und The Art of Data Science (bei beiden handelt es sich um Pay-What-You-Want-Büchern, welche über die von mir gesetzten Links verfügbar sind). Neben anderen Themen beschäftigen sich beide mit etwas, das der wichtigste Schritt im analytischen Prozess sein könnte: wie stellt man sicher, dass die Frage, die sich einem stellt, tatsächlich diejenige ist, die man beantworten möchte. An dieser Stelle gebe ich die Kernbotschaft der entsprechenden Kapitel wieder1. Dabei werden wir einen Blick auf die Arten datenanalytischer Fragen werfen; darauf, was eine gute Frage ausmacht, und darauf, wie man eine Frage in ein Datenproblem umwandelt.

Arten von Fragen

Ein nützliches Gedankengerüst zur Findung einer guten Fragen ist es, sich zuerst selbst bewusst zu machen, welche Arten von Fragen existieren und dann zu entscheiden, welcher Kategorie eine spezielle Frage angehört. Nach Jeff Leek, dem Autor von The Elements of Data Analytic Style, gibt es sechs Arten von datenanalytischen Fragen2. Diese unterscheiden sich nach ihrem Zweck und ihrer Interpreation. Hier sind sie:

fragen arten

Das Flussdiagramm der Arten datenanalytischer Fragen (angelehnt an die Arbeit von Jeff T. Leek und Roger D. Peng3)

  1. Deskriptive
  2. Explorative
  3. Inferentielle
  4. Prädikative
  5. Kausale
  6. Mechanistische

Das Diagramm auf der rechten Seite hilft einem auch dabei, die Kategorie einer Frage zu bestimmen. Das Diagramm, auf dem dieses jenes basiert, kann auch auf Seite 4 in Jeffs Buch gefunden werden. Nun werfen wir einen Blick auf die Konzepte hinter diesen Arten von Fragen.

Deskriptive Fragen verlangen, die Beschaffenheitl eines Datensatzes zusammenzufassen. Beispiele umfassen etwa den Mittelwert, den Median, den Modus, die Varianz, die Standardabweichung oder Schiefe eines Merkmals genauso wie die Häufigkeit eines Ereignisses und den Erwartungswert einer Variablen. Es existiert keine Interpretation des Ergebnisses an sich, denn es handelt sich um einen Fakt.

Eine Explorative Frage baut auf einer desktiptiven Analyse auf. Sie sucht nach Mustern, Trends oder Beziehungen zwischen mehreren Variablen. Deren Hauptabsicht liegt in der Generierung von Hypothesen. Diese können entweder von einer Idee stammen, die man schon vorher hatte, order inspiriert sein von den Beziehungen, die während der Analyse gefunden wurden. Im Gegensatz zu inferentiellen, prädikativen, kausalen und mechanistischen Fragen wird nicht getestet, ob die Hypothese sich als wahr herausstellt.

Eine Inferentielle Frage baut auf einer explorativen Analyse auf. Sie verwandelt die zuvor gefundene Hypothese in eine Frage und strebt an, diese mittels eines fremden Datensatzes zu beantworten. Im Kern dreht sich eine inferentielle Frage darum, zu verifizieren, dass die in einer explorativen Analyse gefundene Evidenz.für eine größere Grundgesamtheit generalisiert werden kann.

Eine Prädiaktive Frage baut auf einer explorativen Analyse auf. Sie strebt an, eine Vorhersage für die Werte für die Merkmale eines spezifischen Individuums zu generieren. Diese Art von Frage beschäftigt sich eher mit dem “was” als dem “warum” oder “wie“. An dieser Stelle ist es wichtiger herauszufinden, welche Faktoren nützlich dafür sind, zu einer richtigen Vorhersage zu gelangen als den Grund für zu ihre Nützlichkeit.

Eine Kausale Frage fragt, ob einen Faktor zu verändern, im Duchschnitt, zu einer Veränderung eines anderen Faktoren führt. Im Gegensatz zu einer prädikativen Fragen ist es wichtiger, harauszufinden, ob eine Veränderung eines Faktoren eine Veränderung eines anderen Faktoren verursacht. Um such selbst den Unterschied bewusst zu machen, ist es nützlich, an Störfaktoren zu denken. Mordraten und Eiscremekonsum in amerikanischen Städten mögen zwar gute Prädiktoren füreinander sein, da sie stark miteinander korrelieren, aber Stieleisverkäufe bewirken schwerlich, dass Mordraten in die Höhe schnellen (und für eine prädikative Frage wäre das in Ordnung). Eine kausale Frage hingegen würde sich mehr dafür interessieren, herauszufinden, dass höhere Temperaturen im Summer der eigentliche Grund für einen steigenden Eiscremekonsum sind (und für höhere Mordraten).

Eine Mechanistische Frage fragt danach, ob einen Faktor zu verändern, notwendigerweise, zu einer Veränderung eines anderen Faktors führt. Sie unterscheidet sich von einer kausalen Fragen darin, dass es nicht nur für das “warum” interessiert sondern auch für das “wie“. Zum Beispiel mögen steigende Temperaturen zwar der Grund hinter steigenden Eiscremeverkäufen sein, aber das zu wissen erklärt nicht, wie genau eines zum anderen führt. In vielen Fällen wird ein sehr spezifischer Versuchsaufbau benötigt, um eine mechanistische Frage zu beantworten. In vielen Fällen besteht der Unterschied zwischen kausalen und mechanistischen Fragen generell weniger in analytischen Techniken als im zur Generierung des Datensatzes verwendeten Versuchsaufbau..

Was macht eine gute Frage aus

Hat man erst einmal herausbekommen, welche Frage man vor sich hat, ist man dazu angehalten, sicherzustellen, dass es auch eine gute Frage ist, bevor man fortfährt. Roger D. Peng und Elizabeth Matsui, die Autoren von The Art of Data Science, schlagen sechs Kriterien vor um genau das zu erreichen. Ihre Kriterien besagen, dass eine Frage folgendermaßen sein sollte:

  • Interessant Bevor man irgendwelchen weiteren Aufwand für die Beantwortung einer Frage verwendet, sollte man sicherstellen, dass es jemanden gibt, der (potentiell) daran interessiert ist, die Antwort zu kennen. Das kann ein ausgedehntes Kriterium sein falls man akademische Forschung betreibt, aber falls man im Gewerbe arbeitet, ist es ratsam, mit seinem Vorgesetzten und/oder  seinen Kollegen zu bestätigen, dass jemand anders an der Antwort einer Frage interessiert ist.
  • Unbeantworted Viele Fragen können einfach durch eine kurze Google-Suche beantwortet werden. Zum Beispiel stellen Behörden wie das U.S. Census Bureau oder das Deutsche Statistische Bundesamt eine Menge öffentlich verfügbarer Daten und Analysen zur Verfügung.  Die Antwort könnte auch inmitten der tausenden wissenschaftlichen Artikel gefunden werden, die jedes Jahr veröffentlicht werden. Falls eine Frage bereits beantwortet ist, gibt es wahrscheinlich keinen Grund dazu, die Analyse zu wiederholen
  • Plausibel So wie mit dem Eiscreme/Verbrechen-Beispiel oben ist es angeraten, dass es ein plausibles Gedankengerüst um eine Frage gibt. Zum Beispiel kann es vor der Durchführung einer Analyse wertvoll sein, zu wissen, bis zu welchem Grad die mögliche Antwort mit Vernunft erklärt werden kann.
  • Beantwortbar Leider können einige der besten Fragen nicht beantwortet werden. Das kann an den Kosten oder Schwierigkeiten liegen, die mit der Sammlung der benötigten Daten verbunden sind, oder an ethischen Gründen. Dennoch sollte eine Frage, der es Wert ist, nachgegangen zu werden, selbstverständlich beantwortbar sein.
  • Spezifisch Eine spezifische statt eine generelle Frage zu haben macht es einfacher, die Art der Frage zu bestimmen und macht es daher auch einfacher, über den Versuchsaufbau und den analytischen Prozess nachzudenken. Auch garantiert es, dass die Frage, die gerade beantwort wird, auch die ist, die jemandens Hörerkreis wirklich beantwortet sehen will. Es ist es daher wert, mit anderen, wie etwa seinen Kollegen, zu überprüfen, ob eine Frage spezifisch ist. Als ein Beispiel kann statt der generellen Frage “Steigen die Gehälter von Fußballspielern?” eine spezifischen etwa:
    • “Werden die inflationsbereinigten festen saisonalen Gehälter von professionellen Football-Spielern in der NFL während der nächsten 12 Monate steifen?” lauten, oder
    • “Wie sehr haben sich die nominalen Gehälter der professionellen Fußballspieler in der 1. Bundesliga, gemssen in Euro, im Laufe der letzten 12 Monate verändert?

    Dieses Beispiel zeigt, dass in vernünftiger Weise die selbe generelle Frage als viele verschiedene spezifische Fragen gedeutet werden kann.  Unspezifische Fragen sind eine potentielle Quelle von Frustration und verschwendeten Ressourcen. Darum sollten Fragen spezifisch sein.

Fragen in Datenprobleme umwandeln

Natürlich ist der Zweck des Stellens einer Frage sie zu beantworten. Im Fall einer datenanalytischen Frage wird man sie durch die Analyse einer Datensatzes beantworten. Daher muss man einmal die Frage in ein Datenproblem übersetzen. Um das zu erreichen, muss man, die Frage in eine Datenanalyse operationalisieren, welche zu einem Ergebnis führt.

Roger D. Peng und Elizabeth Matsui haben darüber nachgedacht, wie man sicherstellen kann, dass eine Frage diese Kriterium erfüllt. Hier ist eine Zusammenfassung ihrer Gedanken in Gestalt einer Checkliste:

  • Stell sicher, dass der Datensatz ausreichend nahe Messwerte der interessierenden Faktoren bereitstellt. Grund dafür ist es, sicherzustellen, dass es nur eine Interpretation der Ergebnisse gibt. Wenn man Messwerte analysiert, die nur irgendwie mit denen verwandt sind, um die es einen tatsächlich geht, gibt es konkurrierende Erklärungen für die Ergebnisse. Zum Beispiel könnte man bestimmen wollen, ob Fußballergehälter gestiegen sind, aber der Meswert, den man verwendet, besteht darin, wieviel diese Fußballer im Vergleich zum Vorjahr ausgegeben haben. Falls man herausfindet, dass die Ausgaben gestiegen sind, gibt es noch immer konkurrierende Erklärungen wie etwa gestiegene Preise für vergleichbare Güter oder eine Veränderung der Präferenzen der Fußballer zwischen Geld ausgeben und Geld sparen. Um das zu vermeiden, muss man einen Messwert benutzen, der näher an den tatsächlichen Gehältern liegt, zum Beispiel die Personalausgaben, die von den Mannschaften angegeben wurden.
  • Denke an Sörfaktoren. Man mag zwar eine Korrelation zwischen zwei Faktoren finden und schlussfolgen, dass einer den anderen herbeiführt, aber man muss vorsichtig damit sein wie das Eiscremebeispiel oben gezeigt hat. Wenn man eine Frage stellt, stelle sicher, dass du Störfaktoren berücksichtigen kannst. Gibt es einen möglichen Störfaktor, der den Personalaufgaben eines Sportvereins steigen lässt, der auch die Gehälter seiner Spieler steigen lässt? Die Inflation könnte solch ein Störfaktor sein. Wenn man sich der Störfaktoren bewusst ist, kann man sie berücksichtigen (falls die erforderlichen Daten einem zur Verfügung stehen) und man kann möglicherweise die Frage ändern (nach den realen Gehaltserhöhungen fragen statt nach den nominalen).
  • Während der Operationalisierung einer Frage in eine Analyse, stelle sicher, dass die Art der Sammlung des Datensatzes nicht zu verzerrten Ergebnissen führt. Nach Peng und Matsui sind Recall Bias und Stichprobenverzerrung die zwei häufigsten Arten von Verzerrung. An dieser Stelle gibt es auch eine komplettere Liste von Stichprobenverzerrungen und eine Liste koginitiver Verzerrungen. Ich werde einen Folgeartikel zu Verzerrungen schreiben und dazu, wie man mit ihnen umgehen kann, da sie manchmal nicht vermieden werden können. Möglicherweise aber kann sowohl die Art, wie man eine Frage stellt, als auch wie man die Datenerhebung und die Analyse operationalisiert, in der Tat eine Verzerrung vermeiden. Also verwende ein paar Minuten dazu, darüber nachzudenken, welche Verzerrungen eine Methode produzieren könnte und ob es eine Möglichkeit gibt, sie zu vermeiden.

Fußnoten

1. Die entsprechenden Kapitel sind Chapter 2: The data analytic question in Jeff Leeks und Chapter 3. Stating and Refining the Question in Roger Pengs and Elizabeth Matsuis Buch.
2. Jeff T. Leek, The Elements of Data Analytic Style, 2015, S. 4-7
3. Jeff T. Leek and Roger D. Peng, What is the question? in Science,  20 March 2015: Vol. 347 no. 6228, S. 13141315, DOI: 10.1126/science.aaa6146
4. Roger D. Peng and Elizabeth Matsui, The Art of Data Science, 2015, S. 20-22

How to Pose a Question

This post is inspired by two books I read during the last couple of days  The Elements of Data Analytic Style and The Art of Data Science (both are pay-what-you-want books and available via the links I provided). Among other topics both deal with what might be the most important step in the analytic process, how to ensure that the question at hand is the one you actually want to answer. Here I reiterate the essence of the corresponding chapters1. Thereby we will take a look at the types of data analytic questions, what makes a good question and how to convert a question into a data problem.

Types of Questions

A useful framework for determining a good question is first making yourself aware of which kinds of questions exist and then determining which category a specific question belongs to. According to Jeff Leek, author of The Elements of Data Analytic Style, there are six types of data analytic questions2. These differentiate in their purpose and their interpretation. Here they are:

question types

The data analysis question type flow chart (based on Jeff T. Leek’s and Roger D. Peng’s work3)

  1. Descriptive
  2. Exploratory
  3. Inferential
  4. Predictive
  5. Causal
  6. Mechanistic

The chart on the right also helps you determining the category of a question. The chart it is based on can also be found on page 4 of Jeff’s book. Now let’s take a look at the concepts behind these types of questions.

Descriptive questions ask to summarize a property of a set of data. Examples include the mean, median, mode, variance, standard deviation or skewness of a feature as well as the frequency of an event and the expected value of variable. There is no interpretation of the result in itself since it is a fact.

An Exploratory question builds on a descriptive analysis. It seeks for patterns, trends or relationships between multiple variables. Their main purpose is generating hypotheses. These can either stem from a general idea you already had or be inspired by the relationships found during the analysis. In contrast to inferential, predictive, causal and mechanistic questions it does not test if the hypothesis holds true.

A Inferential question builds on an exploratory analysis. It turns the formerly found hypothesis into a question and seeks to answer it using a different data set. In essence the inferential questions is about verifying that evidence found in an exploratory analysis can be generalized for a larger population.

A Predictive question also builds on an exploratory analysis. It seeks to generate a forecast for the values of a specific individual’s properties. This type of question is more concerned with the ‘what’ than the ‘why’ and ‘how’. Here it is more important to find which factors are useful for getting the prediction right than the reason behind their usefulness.

A Causal question asks if changing one factor, on average, results in a change in another factor. In contrast to a predictive question it is more important to find if a change in a factor causes a change in another factor. To make yourself aware of the difference it is useful to think of confounding factors. Murder rates and ice cream consumption is US cities might be good predictors for each other since they are highly correlated but Popsicle sales hardly cause murder rates to soar (and a predictive question would be fine with it). A causal question though would be more interested in finding that higher temperatures in summer are the actual reason behind rising ice cream consumption (and higher murder rates).

A Mechanistic questions asks if changing one factor, necessarily, results in a change in another factor. It differs from a causal question in that it is not just interested in the ‘why’ but also the ‘how’. For example rising temperatures might be the cause behind rising ice cream sales but knowing this does not explain how exactly one leads to another. In many cases a very specific test design is needed in order to answer a mechanistic question. In many cases the difference between causal and mechanistic questions is generally less about analytic techniques used than about the test design used to generate the data set.

What makes a Good Question

Once you figured out which type of question you have at hands you are ought to make sure it also is a good question before you proceed. Roger D. Peng and Elizabeth Matsui, authors of The Art of Data Science, suggest six criteria to do just that4. Their criteria are that a question must be:

  • Interesting Before you spent any further effort on answering your question you should make sure that there is (or potentially is) someone interested in finding the answer. This can be a broad criterion in case you are doing academic work but in case you are working in industry it is advised to confirm with your boss and/or colleagues that someone else is interested in the answer to your question.
  • Unanswered Many questions can be easily answered by a quick Google search. For example agencies like the U.S. Census Bureau or the German Federal Statistical Office provide a lot of publicly available data and analyses.  The answer might also be found among the thousands of academic articles published every year. In case your question is already answered there is likely no need to repeat the analysis.
  • Plausible As with the ice cream/crime example above it is advised to make sure there is a plausible framework around your question. So before conducting an analysis it can be worth to come to know to what extent the possible answers can be explained with reason.
  • Answerable Unfortunately some of the best questions cannot be answered. This can be due to the cost or difficulty of collecting the needed data or due to ethical reasons. Still a question worth pursuing should obviously be answerable.
  • Specific Having a specific question rather than a general one makes it easier to determine the type of question and thus makes it easier to think about the test design and the analytic process. It also ensures that the question being answered is the one you and your audience really want to see answered. It’s worth checking with others such as your colleagues if your question is specific. As an example instead of the rather general ‘Are footballer salaries increasing?’ a specific question could be either:
    •  ‘Will the inflation-adjusted fixed seasonally salaries of professional football players in the NFL increase during the next 12 months?‘ or
    • By how much did the nominal salaries of professional soccer players in the 1. Bundesliga measured in Euro change over the course of the last 12 months?

    This example shows that the same general question could reasonably be assumed to mean many different specific ones. Unspecific questions are a potential source of frustration and wasted resources. Thus a good question is specific.

Converting Questions into Data Problems

Of course the aim of posing a question is answering it. In case of a data analytic question you will answer it by analyzing a data set. So at one point you have to translate your question into a data problem. To do this you operationalize the question into a data analysis which leads to a result.

Roger D. Peng and Elizabeth Matsui thought about how to make sure that your question fulfills this criterion. Here is a summary of their thoughts in the form of a checklist:

  • Make sure your data set provides close enough measures of the factors you are after. This is to ensure that there is only one interpretation of the results. When analyzing measures which are only somehow related to what you are really after there are competing explanations for the results. For example you might want to determine if footballer salaries have risen but the measure you use to determine this is how much these footballers were spending compared to a year ago. If you find their expenditures have risen there are still competing explanations such as rising prices for comparable goods or a change in their preferences between spending and saving. To avoid this you have to use a measure that’s closer to the actual salaries, for example the staff expenditures the teams reported.
  • Think about confounding factors. You might find a correlation between two factors and conclude that one causes the other but you have to be careful with this as the ice cream example above has shown. When posing your question make sure you can account for possible confounding factors. Is there a possible confounding factor that lets a sports team’s staff expenditure rise that also lets the salaries of their players rise? Inflation might be such a confounding factor. When you are aware of the confounding factors you can account for them (in case the data needed is available to you) and you can possibly change your question (asking for real increases of salary rather than nominal ones).
  • When operationalizing your question into an analysis, make sure the way your data set was collected does not lead to biased results. According to Peng and Matsui the two main biases to avoid are recall bias and selection bias. Here is also a more complete list of sampling biases and a list of cognitive biases. I am going to write a follow-up article on biases and how to deal with them since sometimes they cannpt be avoided. But possibly the way you pose your question and the way you operationalize the data collection and analysis can indeed avoid bias. So spend a couple of minutes on thinking about which biases your method could produce and if there is any possibility to avoid them.

Footnotes

1. The corresponding chapters are Chapter 2: The data analytic question in Jeff Leek’s and Chapter 3. Stating and Refining the Question in Roger Peng and Elizabeth Matsui’s book.
2. Jeff T. Leek, The Elements of Data Analytic Style, 2015, pp. 4-7
3. Jeff T. Leek and Roger D. Peng, What is the question? in Science,  20 March 2015: Vol. 347 no. 6228, pp. 13141315, DOI: 10.1126/science.aaa6146
4. Roger D. Peng and Elizabeth Matsui, The Art of Data Science, 2015, pp. 20-22

 

Using Python in KNIME

In the beginning I found it can be quite confusing to use Python in KNIME. At least it was in my case, but fortunately I was able to figure out how to go about the integration. Here is how I did it.

The Extensions

First off, I am going to assume that you have a working distribution of Python and KNIME Analytics Platform installed on your machine. In case you can check off these two points, let’s continue. Currently (last update: November 2015) there are two public KNIME Extensions to help you integrating Pyhton in KNIME. These are:

  • KNIME Python Scripting Extension (KNIME Community Contribution – Other)
  • KNIME Python Integration (KNIME Labs Extension)

You can find both of them easily by typing in “python” after clicking on File… -> Install KNIME Extensions… . If you’d like to have a more detailed description read my post on how to install KNIME extensions. Both of them support Python 2.x (recommended Python 2.7) as said on the Extension’s GitHub Wiki. After installing the Extensions you should find them in your Node repository.

python plugins for KNIME

KNIME Python Scripting Extension

Personally I prefer using this extension over the other one for simple transformations due to its simpler interface. The only flaw with it is that it doesn’t use Pandas DataFrames out of the box like most users probably want it to do. Instead the incoming data is handled as an OrderedDictionary. Here is how you can circumvent that, just type the following into the Python Snippet Dialog:

import pandas as pd

# Load your workflow data into a dataframe
df = pd.DataFrame(data=kIn)

# Do some manipulations here

# Send your dataframe down the workflow
pyOut = df

And there you go. Now you can add do sorts of things you would normally do in the Python IDE of your choice, including using libraries. There are two mandatory variables here. kIn (read: K-in) is used for getting the data from the previous node, and pyOut is used for telling KNIME which data you’d like to transmit onto the next node.

In case you want to do a plot, you can also use the Python Plot node. It has the same flaw as above, but on the bright side it’s just as easy to fix as above as well. Here is an example I did for visualizing soccer player data (a Scatter Matrix using Seaborn):

import seaborn as sns
import pandas as pd
sns.set()

 data = kIn 
 df = pd.DataFrame.from_dict(data)

sns.pairplot(df, vars=["height", "weight", "age", "rating"], hue="position",  diag_kind="kde", diag_kws=dict(shade=True))

python scatter plot

KNIME Python Integration

Earlier I said that I prefer the other extension over this one for simple manipulations. Once it gets trickier though this one is clearly more useful to me. Its most prominent advantages are that

  • a) you don’t need to convert the data, this node just gives you a DataFrame right away
  • b) you have a console to work with interactively like you would do in a full-fledged Python IDE and
  • c) there are special nodes for training a model and using models for predictions.

So in the Python Script node the equivalents to kIn and pyOut in the Python Snippet are input_table and output_table. Here’s the most simple thing you can do without breaking the Python Script node.

# Copy input to output
output_table = input_table.copy()

The Python Script (2:1) node is functionally the same. Its small difference is that it takes two tables as input instead of just one.

# Do pandas inner join
output_table = input_table_1.join(input_table_2, how='inner', lsuffix=' (left)', rsuffix=' (right)')

The Python Source node is functionally the same as well but it takes no input at all.

from pandas import DataFrame
# Create empty table
output_table = DataFrame()

There also is an equivalent to the Python Plot node in form of the Python View node. I found that one a little unhandy though since it requires you to save a Figure object into a Buffer. For reference here is the same plot I did above but in the Python View node. You can clearly see that it is much more verbose:

from io import BytesIO
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns

# Create a buffer to write into
buffer = BytesIO()

# Copy data and create plot
df = input_table
sns.set()
sns_plot = sns.pairplot(df, hue="positionText", diag_kind="kde", diag_kws=dict(shade=True), vars = ["height", "weight", "age", "rating"])

# Get the Figure type object from the plot
# and save the it into the buffer
sns_plot.fig.savefig(buffer, format='png')

# Set the buffer's content as output image
output_image = buffer.getvalue()

There are more nodes in the Python Integration Extension, namely the Python Object ReaderPython Object Writer as well as the Python Learner and Python Predictor. Especially the latter ones sound relevant to me. I will take a look at them in a follow-up post.

How to install KNIME Extensions

In this post I am going to show how to add extensions to KNIME Analytics Platform. As an example I use KNIME Decision Tree Ensembles. The version of KNIME I am using is 2.11.3.

For this tutorial I assume that you already started the program and that everything is up and running. All you then really need to do is the following. You can also look at the pictures below:

  • Click on File
  • Click on Install KNIME Extension…
  • This will open a dialog called ‘Install’
  • Now you have two options. You can either
    • a) Type in the name (or a part of the name) into the search box
    • b) Click on the arrows to open the directories and search for Extensions this way
  • Check the extension(s) you want to install
  • Click on Next
  • Now you can review the Extensions you selected
  • If you are satisfied with the selection once again click on Next. 
  • Accept the terms of the license agreement…
  • … and click on Finish

Now the extension will be automatically added to your KNIME distribution. You might need to restart the program in order to use your new features. And you’re done!

 

how to add a KNIME extension

 

install KNIME extension

 

KNIME extension installation

 

KNIME extension dialog

 

KNIME extension selection

 

KNIME extension finish

CeBit-Besuch 2015 – Welche Trends zeichnen sich im Bereich Big Data ab

Heute, Mittwoch dem 18. März 2015, organisierte die Hochschule Wismar für Studierende der Wirtschaftsinformatik sowie weitere Interessenten einen konstenlosen Besuch der IT-Messe CeBit. Ich selbst nahm daran ebenfalls teil. Durch einen unserer Professoren wurde dabei die Aufgabe gestellt, sich auf der Messe gezielt mit einem Thema der eigenen Wahl zu beschäftigen und im Rahmen der nächsten Lehrveranstaltug seine Ergebnisse zu präsentieren. Entsprechende meiner Neigung habe ich mich mit dem Thema Big Data beschäftigt.

Für das Thema relevante Vorträge fanden parallel in Halle 5 und Halle 9, so dass ich nur an einem Teil der Vorträge teilnehmen konnte.

In der folgenden Gegenüberstellung habe ich die Vorträge markiert, an denen ich teilgenommen habe.

cebit 2015 halle 5 halle 9

    Im Einzelnen sind das also:

  • – Digitale Transformation: BI und Big Data treiben neue Geschätsmodelle
  • – Data Virtualization als Motor für Big Data in Unternehmen
  • – Multiprojektcontrolling im Big Data Zeitalter
  • – Massiv parallele Datenverarbeitung mit Microsoft PDW
  • – Wouldn’t Analytics be easier if Hadoop was Code-free?
  • – Lernen sichtbar machen: Big Data, Smart Data und Open Data im Bildungsbereich
  • – Visual Business Analytics
  • – Industrie 4.0 startet ins Web of Things

Zu sehen sind auch vortragsfreie Zeiten. In denen hatte ich mich umgesehen, was es sonst noch an Ausstellungen gibt sowie mit einigen Leuten geredet. Am interessantesten ist jedoch welche Beobachtungen ich denn nun gemacht habe. Vor allem zwei große Schlagwörter haben sich in den Vorträgen wiederholt. Das sind zum einen (Big) Data Visualization und zum anderen Data Virtualization.

Data Visualization

Im Kern geht es darum, aus großen Datenmengen für Menschen möglichst intuitiv interpretierbare Illustrationen zu schaffen. Das ist an sich nichts Neues. Unter dem Begriff Visual Analytics ist diese Bestrebung spätestens seit 2004 bekannt. Allerdings scheint sie aktuell an Bedeutung gewonnen zu haben. An mindestens jedem dritten  bis zweiten Stand in Halle 9 fand sich in irgendeiner Form das Versprechen, komplexe Daten einfach verständlich zu illustrieren. Im “future talk”  “Visual Business Analytics” durch Dr. Kohlhammer vom Fraunhofer Instituts für Grafische datenverarbeitung(IGD) wurde der Nutzen an erster Stelle mit dem entstehenden Zeitgewinn genannt. Der Mensch verarbeite visuelle Darstellungen einfach schneller als Zahlen. Ein weiterer Nutzen entsteht nach ihm außerdem durch ein besseres Verständnis der Daten an sich. Durch die graphische Darstellung ergäbe sich womöglich sogar neues Wissen über die Daten, das Analyseverfahren entgangen wäre. Zuletzt würde durch die Möglichkeit der Visualisierung auch das Vertrauen in Analyseergebnisse gestärkt werden.

Data Virtualization

Data Virtualization ist in seinem Grundgedanken ebenfalls nichts wirklich Neues. In den Vorträgen zum Thema wurde deutlich, dass Data Vistualization als Nachfolge-Konzept zum Data Warehousing verstanden werden kann. Es geht darum, den über verschiedene Anwendungen und Datenbanken(ERP-System, Data Warehouse, Cloud, Hadoop etc.) verstreuten Daten eines Unternehmens mittels Middleware eine einheitliche Schnittstelle zu verleihen. Für den Nutzer soll sich der Eindruck eines uniformen Datensatzes einstellen. Der Nutzen wird darin gesehen, Datenanalysten den Rücken von freizuhalten von den Mühen der Datenzusammenführung. So sollen mehr Freiräume für die eigentliche Analysearbeit geschaffen werden. Ein zusätzlicher Nutzen entstehe nach Dr. Kurze (denodo) durch die Reduktion von Redundanzen. Derzeit sei ein Datensatz innerhalb eines Unternehmens durchschnittlich 8-10 Mal hinterlegt und durch die Zusammenführung in der Middleware trete eine Vereinfachung ein.  Zudem würde die Zugriffskontrolle auf die Daten (“wer kann was sehen”) erheblich vereinfacht.

Welche Länder werden am häufigsten in den Nachrichten erwähnt?

 

 

Wie in meinem Beitrag über GDELT und Google BigQuery erwähnt, habe ich selbst auch deren Benutzung erprobt. Inspiriert von Felipe Hoffas Post habe ich mich gefragt, über welche Länder im Jahr 2015 bisher am meisten geschrieben wurde. Um es kurz zu machen, das Ergebnis lautet folgendermaßen:

  1. USA
  2. GBR
  3. FRA
  4. RUS
  5. CAN
  6. AUS
  7. CHN
  8. ISR
  9. NGA
  10. DEU

länder nachrichten häufig erwähnt

 

Im Folgenden beschreibe ich meine Vorgehensweise und beantworte ein paar andere Fragen, die ich mir im Zusammenhang mit dem Datensatz außerdem gestellt habe.

Die Datenbeschaffung

Zunächst benötigte ich also erst einmal die Daten. Die standen glücklicherweise mit der GDELT-Datenbank auf Google BigQuery schon bereit. Alles was ich tun musste, war es, die richtige Abfrage zu stellen.

SELECT count(*) Anzahl, Actor1CountryCode, Year
FROM [gdelt-bq:full.events] 
WHERE Actor1CountryCode != ''
GROUP BY Actor1CountryCode, Year
ORDER BY Anzahl DESC, Year DESC

Das Ergebnis kann auf BigQuery direkt als CSV-Datei gespeichert werden. Diese habe ich zunächst über die Funktion Import Dataset in RStudio importiert. Dem data.frame hab eich den Namen news gegeben und als Datensatz von besonderem Interesse eingebunden.

attach(news)

Die Beantwortung der Fragestellung war nun recht einfach.

Die Lösung der Ausgangsfragestellung

Im Grunde lässt sich das Ergebnis bereits aus den Daten ablesen so wie ich sie mit der SQL-abfrage erhalten habe, da ich die Angabe

ORDER BY Anzahl DESC, Year DESC

eingefügt habe. Damit ist das Ergebnis im Prinzip bereits direkt ablesbar. Unten ist jedoch noch eine sichere Methode mit R, mit der man auch zu dem selben Ergebnis gelangt, selbst wenn mir ein komplett ungeordneter Datensätze vorgelegen hätte.

news2015 = subset(news,Year==2015)
head(news2015$Actor1CountryCode[order(news2015$Anzahl,decreasing=T)],10)
alternativ: 
head(Actor1CountryCode[order(subset(Anzahl,Year==2015),decreasing=T)],10)

Das selbe lässt sich nun mit jedem beliebigen Jahr zwischen 2015 und 1979 wiederholen indem “2015” durch das Jahr ersetzt wird. Im Jahr 2014 waren USA, GBR, FRA, RUS, CAN, AUS, CHN, ISR, NGA und DEU ebenfalls die meistgenannten Länder.

 Weitergehende Fragen

Ich wollte wissen, für wie viele Länder und wie viele Jahre überhaupt Daten vorhanden sind. Das Ergebnis: für 224 Länder und 37 Jahre.

length(table(Actor1CountryCode))
length(table(Year))

Danach habe ich mich gefragt, ob auch für jedes Land in jedem der 37 Jahre Daten vorhanden sind. Das Ergebnis: Nein. Für 26 Länder bzw. 11,6% der Länder ist nicht in jedem Jahr ein Eintrag vorhanden.

length(subset(table(Actor1CountryCode),table(Actor1CountryCode)!=37))
length(subset(table(Actor1CountryCode),table(Actor1CountryCode)!=37))/length(table(Actor1CountryCode))*100

Bei den 26 Ländern, die nicht in jedem Jahr Erwähnung finden handelt es sich um die, mit den CountryCodes  COK, MHL, SLB, VUT, ABW, AIA, GEO, TUV, SCN, SMR, CAS, EAF, LAM, AND, ROM, SAF, SAM, WLF, HKG, EEU, NAF, CAU, PRI, TWN, SSD und BLK. Dabei wurden BLK und SSD nur in 2 bzw. 5 Jahren erwähnt während COK und MHL hingegen nur in einem Jahr nicht erwähnt wurden. Die genau Verteilung habe ich anschließend in einem Barplot visualisiert.

table(Actor1CountryCode)[tail(order(table(Actor1CountryCode),decreasing=T),26)]
barplot(table(Actor1CountryCode)[tail(order(table(Actor1CountryCode),decreasing=T),26)])

am seltensten erwähnte LänderZum Abschluss habe ich mich noch gefragt, welche Länder die All-time-Hitliste der meist erwähnten Länder anführen. Das Ergebnis: Die ersten 9 Plätze der Top 10 gehen an die USA mit Erwähnungen aus den Jahren 2014, 2012, 2013, 2011, 2010, 2009, 2008, 2007 und 2015. Auf Platz 10 folgt Großbritannien mit dem Wert aus 2014. Damit kann man schon jetzt festhalten, dass die USA 2015 in weniger als zwei Monaten mehr Erwähnungen erreicht haben als der Rest der Welt in jedem beliebigen gesamten Jahr. Deutschland erscheint in der Liste übrigens zum ersten Mal auf Platz 67 mit seinem Wert von 2014.

head(news$Actor1CountryCode[c(order(Anzahl,decreasing=T))],10)
head(news$Year[c(order(Anzahl,decreasing=T))],10)

GDELT und Google BigQuery

Heute morgen bin ich gleich auf zwei sehr interessante Projekte gestoßen. Zum einem ist da GDELT, zum anderen Google BigQuery.

Was ist GDELT?

GDELT  steht für Global Database of Events, Language and Tone. Eine Selbstbeschreibung des Zwecks von GDELT lautet folgendermaßen:

“GDELT monitors the world’s news media from nearly every corner of every country
in print, broadcast, and web formats, in over 100 languages,
every moment of every day.”

Das Unternehmen stellt der Welt eine mehrere Gigabyte umfassende Datenbank zur kostenlosen Verfügung. Sie kann nicht nur mit Hilfe der Unternehmenswebseite ausgewertet werden sondern auch vollumfänglich heruntergeladen werden. Konkret in der Datenbank zu finden sind Metainformationen zu News-Artikeln, die seit dem 01. Januar 1979 veröffentlicht werden. Metainformationen sind Informationen wie Beispielweise der Erscheinungstag, -monat und -jahr, das Erscheinungsland, aber auch Informationen wie das Thema, der Hauptakteur und die emotionale Stimmung.

Was ist Google BigQuery?

Google BigQuery ist wie der Name verrät ein Angebot von Google; ähnlich wie Google Docs oder Google Drive. BigQuery bietet die Möglichkeit Googles Infrastruktur zu nutzen, um rechenintensive Datenbankabfragen in kurzer Zeit zu bewerkstelligen; ist also vergleichbar mit Amazons Cloudservice. Die Bedienung von BigQuery ist schnell erklärt. Zur Abfrage von Datenbanken werden SQL-artige Anfragen in ein Eingabefeld getippt und mit einem Klick auf “Run Query” die Abfrage gestartet. Hier sind einige Beispiele für eine solche Abfragen. Zunächst eine eigene Abfrage, die anzeigt, wie viele Einträge über Ereignisse in einem bestimmten Land in einem Jahr vorhanden sind.

SELECT count(*) Anzahl, Actor1CountryCode, Year
FROM [gdelt-bq:full.events] 
WHERE Actor1CountryCode != ''
GROUP BY Actor1CountryCode, Year
ORDER BY Anzahl DESC

Die zweite Abfrage stammt von Google-Mitarbeiter Felipe Hoffa, der untersucht hat, in welchen Monaten Chile besonders häufig Erwähnung fand.

SELECT TIMESTAMP(STRING(MonthYear)+’01') month,
       SUM(ActionGeo_CountryCode=’CI’)/COUNT(*) Chile,
FROM [gdelt-bq:full.events]
WHERE MonthYear>0
GROUP BY month
ORDER BY month


Abfragen auf BigQuery können allerdings auch eine etwas komplexere Gestalt annehmen, wie dieses weitere Beispiel von Hoffa bezeugt. Es fragt ab vereinfacht gesagt ab, welche zehn Wörter in den vergangenen 24 Stunden am häufigsten in den Schlagzeilen von Artikeln Erwähnung fanden.

SELECT word, c FROM ( 
  SELECT word, COUNT(*) c FROM ( 
    SELECT SPLIT(SOURCEURL, '-') word FROM ( 
      SELECT REGEXP_REPLACE(REGEXP_REPLACE(LOWER(SOURCEURL), r'.*//[^/]*/', ''), r'[/\._]', '-') SOURCEURL 
      FROM [gdelt-bq:full.events@-86400000-] 
      WHERE DOMAIN(SOURCEURL) IS NOT null 
      GROUP BY SOURCEURL)) 
  WHERE REGEXP_MATCH(word, '^[a-zA-Z]*$') 
  GROUP BY word HAVING c>30) 
  WHERE word NOT IN ( 
SELECT word FROM ( 
  SELECT word, COUNT(*) c FROM ( 
    SELECT SPLIT(SOURCEURL, '-') word FROM ( 
      SELECT REGEXP_REPLACE(REGEXP_REPLACE(LOWER(SOURCEURL), r'.*//[^/]*/', ''), r'[/\._]', '-') SOURCEURL 
      FROM [gdelt-bq:full.events@-1209600000--86400000] 
      WHERE DOMAIN(SOURCEURL) IS NOT null 
      GROUP BY SOURCEURL )) 
    WHERE REGEXP_MATCH(word, '^[a-zA-Z]*$') 
    GROUP BY word 
    ORDER BY c DESC LIMIT 500 
  ) 
) 
ORDER BY c DESC 
LIMIT 10

Unter dem obigen Link findet sich auch eine Erklärung zu einzelnen Teilen der Abfrage. Mit hat es jedenfalls geholfen, meine SQL-Kenntnisse aufzufrischen.

Google stellt die Nutzung von BigQuery ebenfalls kostenlos zur Verfügung, jedenfalls falls man sich auf öffentlich zugängliche Datensätze beschränkt, die zudem bereits von Google gehostet werden. Dazu zählen beispielsweise Eurostat- oder OECD-Statistiken. Die ca. 250 Millionen Einträge der “GDELT-bq:full.events”-Datenbank mit 58 Feldern pro Zeile stellt Google ebenfalls bereit, worauf GDELT und die Suchmaschine gleichermaßen stolz verweisen. Dies ist auch der Grund, warum ich kurz nach GDELT auch auf BigQuery gestoßen bin.

Hier ist ein Beitrag, in dem ich beschreibe, wie ich selbst GDELT und Google BigQuery für eine einfache Analyse benutzt habe.

Visualisierung – Transfers von Fußballspielern

Letztens habe ich eine interessante Visualisierung von Daten auf www.eyeseedata.com gefunden. Leider wird an keiner Stelle genannt woher die benutzten Daten stammen, ich hätte gerne einmal ein Auge auf die Quelle geworfen. Die benutzten Daten umfassen 113 Jahre Fußballtransfers zwischen 170 Ländern. Die Daten können auch heruntergeladen werden, indem im Tab Transfer History in der rechten unteren Ecke zunächst auf Download und anschließend auf Data geklickt wird. Der Klick auf Data öffnet ein neues Fenster, in dem die Daten heruntergelden werden können. Den vollen Datensatz erhält man jedoch nur, indem in neuen Fenster auf underlying angeklickt und anschließend ein Haken in der entsprechenden Box gesetzt wird.

Auf der Seite können verschiederene Visualisierungen gefunden werden. Auf der hier gezeigten ist es möglich, zu sehen wie viel Geld in den 113 Jahren insgesamt für Spieler aus welchem Land ausgegeben wurde und für welche Anzahl an Spielern. Der für mich interessante Fall ist Deutschland. Man kann sehen, dass nur mehr Transfers von englischen Spielern stattgefunden haben als von deutschen. Mit weitem Abstand folgen Brasilien, Frankreich und Argentinien. Erst dann platzieren sich die beiden anderen europäischen Schwergewichte Italien und Spanien auf Platz 6 bzw. 7.

Zu sehen ist allerdings auch, dass für Spieler aus den meisten großen Ländern der Fußballwelt mehr Geld ausgegeben wurde als für solche aus Deutschland; und zwar schon bevor man den Wert pro Spieler betrachtet. So wurde für Spieler aus den Niederlanden ca. die selbe absolute Summe umgesetzt wie für deutsche, allerdings für ca. 2700 Spieler statt für ca. 6200. Pro Spieler aus den Niederlanden wurde also in etwa 130% mehr ausgegeben als für einen Deutschen. Die Spieler, mit denen in den 113 Jahren die größten Summen umgesetzt wurden, stammen aus Spanien, Italien, Brasilien, Frankreich und England. Die ca. 2,5 Mrd. Euro für spanische Spieler stehen ca. 1,1 Mrd. für deutsche gegenüber. Historisch gesehen waren deutsche Spieler also im Schnitt ungleich billiger als ihre Kollegen aus z.B. Spanien, Italien, Frankreich, England, Brasilien etc..

statistik bundesliga

 

Auf eyeseedata.com ist auch eine Visualisierung historischer FIFA-Rankings verschiedener Nationen zu finden.

OECD – The Metropolitan Century

Seit einiger Zeit folge ich auf Facebook der Seite “OECD Statistik des Tages“. Dort wird täglich eine neue Visualisierung einer der zahlreichen OECD-Statistiken veröffentlicht. Heute war es dieser Beitrag.

OECD Urbanisierung Statistik

 

Zunächst hat mich natürlich interessiert, wie Deutschland in dem Ranking abschneidet. Zu sehen ist, dass von den 29 gelisteten Ländern Deutschland (38,8%) im Jahr 2012 an 15. Stelle steht, also ganz genau in der Mitte. Der OECD-Schnitt (48,6%) liegt jedoch weit höher. Das ist damit zu erklären, dass die OECD-Mitgliedstaaten mit einem überdurchschnittlichen Urbanisierungsgrad gleichzeitig zu den einwohnerstärksten gehören (zum Vergleich: USA 317 Mio., Japan 128 Mio., Mexiko, 120 Mio., Deutschland 80. Mio).

Dies gilt allerdings nur bei der Betrachtung von Ballungsräumen mit mehr 500,000 Einwohnern. Betrachtet man hingegen Städte ab einer Einwohnerzahl von 50,000 verändert sich das Bild. Bei dieser Sortierung würde Deutschland (Urbanisierung 63,7%) an 12. Stelle liegen; knapp vor Mexiko (62,0%), knapp hinter Frankreich (65,3%) und somit immer noch hinter dem entsprechenden OECD-Schnitt (66,9%).

Nach der Grafik habe ich mir die zugehörige Studie namens The Metropolitan Century – Understanding Urbanisation and its Consequences etwas genauer angesehen. Besonders interessiert hat mich die Frage, ob große Städte einen überwiegend positiven oder negativen Einfluss auf ihr Land haben (S.96-110). Hier sind einige der interessanteren Ergebnisse der Studie:

  • In der OECD gibt es 1179 Städte mit 50,000 oder mehr Einwohnern.
  • In der OECD gibt es 275 Städte mit 500,000 oder mehr Einwohnern.
  • Die 48,6% der OECD-Bevölkerung in Ballungsgebieten erbringt 55% der Wirtschaftsleistung.
  • Die 48,6% der städtischen Ballungsräumen trug zwischen 2000 und 2010 genau 50% zum gesamten Wirtschaftswachstum in der OECD bei. [Eigene Bemerkung: Dabei ist zu beachten, dass zwischen 2000 und 2010 der Anteil der städtischen Bevölkerung in der OECD gestiegen ist. Die Aussage ist also ungenau und es ist davon auszugehen, dass der Anteil am Wirtschaftswachstum 2010 höher war als im Jahr 2000. ]
  • Nicht nur die Größe von Städten ist für den Wohlstand eines Landes von Bedeutung sondern auch ihre räumliche Verteilung. So erzielen polyzentrische Länder (z.B. USA, Deutschland, Spanien) im Schnitt ein höheres BIP pro Einwohner als Länder mit einer einzigen großen Stadt (z.B. Chile, Ungarn, Irland). Als Grund genannt wird, dass durch den Polyzentrismus größere Teile des Landes durch die Nähe zu einer großen Stadt profitieren (z.B. Wismar zu Hamburg, Landshut zu München).
  • Das Wirtschaftswachstum pro Jahr pro Einwohner liegt innerhalb der OECD in Ballungsgebieten ca. 0,2% höher als im Landesdurchschnitt. Zusätzlich wirkt sich Nähe zu einem Ballungsraum messbar positiv auf das Wirtschaftswachstum einer Region aus.economic growth proximity to large cities
  • Das selbe gilt auch für das Bevölkerungswachstum einer Region.population growth in rural areas
  • Mit steigender Bevölkerungsdichte fallen die durch Transport entstehenden CO2-Emissionen pro Einwohner.co2 emissionen population density

 

Damit möchte ich diesen Beitrag abschließen. Wer den kompletten Report lesen möchte ohne ihn herunterladen zu müssen kann dies hier tun.