Datenaufbereitung für ggplotting
An dieser Stelle beschreiben wir kurz, wie die Daten für die ggplotting-Inhalte zustande gekommen sind. Den fertigen Datesatz zum Download stellen wir auch direkt bereit, aber mit den hier dargestellten Befehlen kann dieser komplett ohne irgendwelche Schritte außerhalb R erzeugt werden.
Daten von Gapminder
Gapminder stellt online ein Dashboard zur Interaktion mit diversen Daten auf nationaler Ebene zur Verfügung. Neben der interaktiven Oberfläche stellen Gapminder aber auch noch statisch alle Datensaätze über ihr GitHub-Repository zur Verfügung. Das ist für unseren Gebrauch perfekt, weil die Daten im .csv-Format vorliegen und somit direkt aus R abrufbar sind.
Um mir die Arbeit mit den Daten ein wenig zu erleichtern, nutze ich an dieser Stelle dplyr
- ein weit verbreitetes Paket für das Datenmanagement in R. Das Paket ist wie ggplot2
auch Teil des tidyverse. Es ist nicht zwingend erforderlich das Paket zu nutzen, aber es enthält ein paar Funktionen, die besonders das zusammenführen verschiedener Datensätze erheblich vereinfachen.
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
Die Datensätze, die wir benutzen werden können größtenteils über das github-Repository von Gapminder bezogen werden. Die Dateinamen sind dabei zwar gut strukturiert, aber nicht unbedingt kurz, wodurch die folgenden paar Zeilen R code etwas unübersichtlich wirken können.
# Geografische Informationen
raw_geo <- read.csv('https://github.com/open-numbers/ddf--gapminder--systema_globalis/raw/master/ddf--entities--geo--country.csv')
# Populationsdaten
pop <- read.csv('https://github.com/open-numbers/ddf--gapminder--systema_globalis/raw/master/countries-etc-datapoints/ddf--datapoints--population_total--by--geo--time.csv')
# Lebenserwartung
expect <- read.csv('https://github.com/open-numbers/ddf--gapminder--systema_globalis/raw/master/countries-etc-datapoints/ddf--datapoints--life_expectancy_at_birth_with_projections--by--geo--time.csv')
# Einkommen (GDP / Person)
income <- read.csv('https://github.com/open-numbers/ddf--gapminder--systema_globalis/raw/master/countries-etc-datapoints/ddf--datapoints--income_per_person_gdppercapita_ppp_inflation_adjusted--by--geo--time.csv')
# Investition in Bildung (nach Bildungsstufe getrennt)
primary <- read.csv('https://raw.githubusercontent.com/open-numbers/ddf--gapminder--systema_globalis/master/countries-etc-datapoints/ddf--datapoints--expenditure_per_student_primary_percent_of_gdp_per_person--by--geo--time.csv')
secondary <- read.csv('https://raw.githubusercontent.com/open-numbers/ddf--gapminder--systema_globalis/master/countries-etc-datapoints/ddf--datapoints--expenditure_per_student_secondary_percent_of_gdp_per_person--by--geo--time.csv')
tertiary <- read.csv('https://raw.githubusercontent.com/open-numbers/ddf--gapminder--systema_globalis/master/countries-etc-datapoints/ddf--datapoints--expenditure_per_student_tertiary_percent_of_gdp_per_person--by--geo--time.csv')
Zuerst benötigen wir ein paar Informationen über die Länder, die wir später vielleicht noch gebrauchen können. Dazu benutzen wir hier mal ein paar grundlegende geografische Informationen (raw_geo
), die Bevölkerungsgröße (pop
), die Lebenserwartung (expect
) und das skalierte Bruttoinlandsprodukt (GDP / Person, income
). Als Bildungsindikatoren haben wir außerdem die Investitionen ins Bildungssystem durch die jeweiligen Nationen in Prozent der jährlichen Wirtschaftsleistung einer Person (GDP / Person). Diese werden bei der Weltbank in drei Sektoren unterteilt: primary (in Deutschland z.B. die Grundschule), secondary (in Deutschland z.B. Sekundarschulen, Gymnasien und Berufsschulen) und tertiary (in Deutschland z.B. Universitäten und Berufsakademien).
Ein letzter Datensatz stammt auch von Gapminder, ist allerdings ein berechneter Index, sodass er in einem anderen GitHub Repository zu finden ist. Hier handelt es sich um den Education Index, der von United Nations Development Programme veröffentlicht wird. Leider ist in diesem Datensatz die Benennung des Länder-Code anders, als in den Datensätzen aus dem Rohdaten-Repository, sodass wir diesen noch schnell den einheitlichen Namen geben:
# Education Index
index <- read.csv('https://github.com/open-numbers/ddf--gapminder--fasttrack/raw/master/ddf--datapoints--owid_education_idx--by--country--time.csv')
names(index)[1] <- 'geo'
Verschiedene Informationen zusammenführen
Diese Quellen an Information müssen wir in einen Datensatz zusammenführen, bevor wir sie in einer gemeinsamen Grafik darstellen können. Dazu möchte ich zunächst die geografischen Daten auf den Umfang notwendiger Informationen herunter reduzieren:
geo <- transmute(raw_geo, geo = country, Country = name, Wealth = income_groups, Region = world_4region)
Hier kommt die transmute
-Funktion aus dem dplyr
-Paket zum Einsatz, die einen Datensatz (raw_geo
) entgegennimmt und einen neuen Datensatz mit erstellten Variablen ausgibt. Hier benutze ich den Datensatz nur dazu, Variablen umzubenennen und gleichzeitig alle anderen Variablen wegzuwerfen. Im neuen Datensatz sind also nur noch vier Variablen übrig:
names(geo)
## [1] "geo" "Country" "Wealth" "Region"
Diese geschrumpften Informationen müssen jetzt zunächst mit den Informationen zum den Ländern zusammengeführt werden.
geo <- right_join(geo, pop, by = 'geo') |>
full_join(expect, by = c('geo', 'time')) |>
full_join(income, by = c('geo', 'time'))
Hier kommen dplyr
Funktionen zum Einsatz, die auf _join
enden, um zwei Datensätze zusammenzuführen. In der ersten Zeile wird also der Datensatz mit den geografischen Informationen mit dem Datensatz zu den Bevölkerungszahlen zusammengeführt. right_join
heißt dabei, dass alle Zeilen des rechten Datensatzes erhalten bleiben sollen. Zeilen im linken Datensatz, für die es keinen Partner auf der Matchingvariable geo
gibt, werden verworfen. Anders als die geografischen Informationen in geo
enthalten die anderen Datensätze Informationen, die sich mit der Zeit ändern. Daher enthalten diese Datensätze pro Land mehrere Datenpunkte zu unterschiedlichen Jahren, weswegen alle Zeilen des rechten Datensatzes beibehalten werden sollen. Die Länder im linken Datensatz, für die diese Informationen nicht vorliegen werden aber nicht in den gemeinsamen Datensatz übernommen, weil wir für diese keine weitere Verwendung haben.
Dieser Datensatz aus geografischen Daten und Bevölkerungszahlen wird dann mit den lang-ersehnten und in R Version 4.0.0 endlich eingetroffenen nativen Pipe-Operator |>
in die nächste Zusammenführung mit der Lebenserwartung weitergrereicht. Dabei wird das Ergebnis einer Funktion von Links nach Rechts an eine neue Funktion als erstes Argument weitergegeben. Dazu wird full_join
genutzt, weil beide Seiten jetzt Informationen über die Jahre hinweg enthalten, die von beiden Seiten jeweils beibehalten werden sollen. Damit die richtigen Jahre einander zugeordnet werden, benutzen wir außerdem als Matchingvariable jetzt nicht nur den Ländercode geo
sondern auch die Jahreszahl time
.
Die globalen Informationen über Länder sollen jetzt noch mit den spezifischen Bildungsinvestitionen zusammengeführt werden. Dazu kombinieren wir erst alle Bildungsinformationen in einen Datensatz:
edu <- full_join(primary, secondary, by = c('geo', 'time')) |>
full_join(tertiary, by = c('geo', 'time')) |>
full_join(index, by = c('geo', 'time'))
Hier benutzen wir full_join
weil alle Datenpunkte aus beiden Datensätzen einbezogen werden sollen. Wenn die Ausgaben für Primär- und Sekundärbildung zusammengeführt sind, werden sie mit der Pipe |>
an full_join
weitergegeben und dort mit der Tertiärbildung zusammengeführt. Zu guter Letzt verbinden wir die geografischen und die bildungsbezogenen Informationen noch:
edu_exp <- full_join(geo, edu, by = c('geo', 'time'))
Weil die uns hauptsächlich interessierenden Daten zu den Bildungsausgaben erst ab 1997 zuverlässig erhoben wurden, Lebenserwartung und Bevölkerungszahlen aber von 1800 bis 2100 geschätzt bzw. aufgezeichnet wurden, schränken wir den Datensatz noch auf die Spanne von 1997 bis 2017 ein und entfernen die Datenpunkte, die nicht eindeutig einem Land zugewiesen werden konnten:
edu_exp <- filter(edu_exp, time < 2018 & time > 1996) |>
filter(!is.na(Country))
Die Namen der Variablen im Datensatz sind jetzt immmernoch alles andere als schön:
names(edu_exp)
## [1] "geo"
## [2] "Country"
## [3] "Wealth"
## [4] "Region"
## [5] "time"
## [6] "population_total"
## [7] "life_expectancy_at_birth_with_projections"
## [8] "income_per_person_gdppercapita_ppp_inflation_adjusted"
## [9] "expenditure_per_student_primary_percent_of_gdp_per_person"
## [10] "expenditure_per_student_secondary_percent_of_gdp_per_person"
## [11] "expenditure_per_student_tertiary_percent_of_gdp_per_person"
## [12] "owid_education_idx"
Weil wir die Variablen immer und immer wieder im Code ansprechen müssen, machen sich besonders prägnante, kurze Variablennamen gut. Die aktuellen Namen sind leider keins von beidem, daher müssen neue her:
names(edu_exp)[-c(1:4)] <- c('Year', 'Population', 'Expectancy', 'Income', 'Primary', 'Secondary', 'Tertiary')
## Warning in names(edu_exp)[-c(1:4)] <- c("Year", "Population", "Expectancy", :
## number of items to replace is not a multiple of replacement length
Überblick über die finalen Daten
Der Datensatz mit dem wir weiter arbeiten sieht also so aus:
head(edu_exp)
## geo Country Wealth Region Year Population Expectancy Income Primary
## 1 afg Afghanistan low_income asia 1997 19357126 53.74 865 NA
## 2 afg Afghanistan low_income asia 1998 19737770 52.80 800 NA
## 3 afg Afghanistan low_income asia 1999 20170847 54.43 735 NA
## 4 afg Afghanistan low_income asia 2000 20779957 54.63 687 NA
## 5 afg Afghanistan low_income asia 2001 21606992 54.76 646 NA
## 6 afg Afghanistan low_income asia 2002 22600774 55.65 1016 NA
## Secondary Tertiary Year
## 1 NA NA 13.33333
## 2 NA NA 13.33333
## 3 NA NA 14.00000
## 4 NA NA 14.66667
## 5 NA NA 14.66667
## 6 NA NA 15.33333
Eine kurze Erläuterung der Variablenbedeutungen:
geo
: Länderkürzel, das zur Identifikation der Länder über verschiedene Datenquellen hinweg genutzt wirdCountry
: der Ländername im EnglischenWealth
: Wohlstandseinschätzung des Landes, unterteilt in fünf GruppenRegion
: Einteilung der Länder in die vier groben Regionenafrica
,americas
,asia
undeurope
Year
: JahreszahlPopulation
: BevölkerungExpectancy
: Lebenserwartung eines Neugeborenen, sollten die Lebensumstände stabil bleiben.Income
: Stetiger Wohlstandsindikator für das Land (GDP pro Person)Primary
: Staatliche Ausgaben pro Schüler*in in der primären Bildung als Prozent desincome
(GDP pro Person)Secondary
: Staatliche Ausgaben pro Schüler*in in der sekundären Bildung als Prozent desincome
(GDP pro Person)Tertiary
: Staatliche Ausgaben pro Schüler*in oder Student*in in der tertiären Bildung als Prozent desincome
(GDP pro Person)Index
: Education Index des United Nations Development Programme
Eine Ausprägung von 100 auf der Variable Primary
in Deutschland hieße also zum Beispiel, dass pro Schüler*in in der Grundschule das Äquivalent der Wirtschaftsleistung einer bzw. eines Deutschen ausgegeben würde. 50 hieße entsprechend, dass es die Hälfte dieser Wirtschaftsleistung in diese spezifische Schulausbildung investiert wird.