Es gibt Situationen, in denen Daten vom Long-Format (was damit gemeint ist, wird gleich klar) ins Wide-Format umgewandelt werden müssen – und umgekehrt. Reale Daten liegen in den unterschiedlichsten Formaten vor, aber viele R-Funktionen sind auf eine bestimmte Form ausgelegt.
So sind etwa lme4::lmer() für gemischte lineare Modelle oder ggplot2::ggplot() für Visualisierung auf Long-Form ausgelegt. Andere Funktionen wie mosaicplot() erwarten hingegen Wide-Form. Das bedeutet: Wenn deine Daten nicht bereits passend aufbereitet sind, musst du für Analyse oder Visualisierung das Format wechseln.
In R gibt es mehrere Wege für Formatumwandlungen – gerade am Anfang kann das verwirrend sein.
In diesem Tutorial lernst du die Mechanik hinter der Umwandlung zwischen Long- und Wide-Form kennen. Dich erwarten folgende Themen:
Du lernst, was die Long-Form ausmacht.
Dann erfährst du, was die Wide-Form ist.
Du wiederholst die Unterschiede zwischen Long- und Wide-Format.
Im Anschluss siehst du, welche Schritte nötig sind, um von einer Form in die andere zu wechseln.
Zum Schluss setzt du alles in R um: Du lernst, wie du mit den Funktionen melt() und dcast() vom Long- ins Wide-Format und zurück wechselst.
Die Daten
Tabelle 01
name
gender
year2011
year2012
year2013
year2014
year2015
Jackson Smith
M
74.69
84.99
91.73
105.11
111.04
Sophia Johnson
F
NA
NA
NA
NA
75.89
Emma Williams
F
NA
NA
75.74
86.50
91.50
Aiden Jones
M
NA
NA
NA
71.89
81.42
Liam Brown
M
88.24
96.91
101.85
108.13
112.45
Lucas Davis
M
70.60
83.78
94.17
100.03
106.35
Olivia Miller
F
64.78
80.76
87.30
97.13
103.80
Ava Wilson
F
88.77
96.45
104.72
112.84
NA
Die Tabelle zeigt die Größe von Babys in einem kleinen Einzugsgebiet. Gemessen wurde von 2011 bis 2015. Wie du sicher weißt, bedeutet NA „Not Available“ (nicht verfügbar). Anhand der Positionen der NAs lässt sich das Alter der Babys ableiten, aber das exakte Alter ist der Tabelle nicht zu entnehmen. Die Tabelle wirkt ordentlich, doch wer das Wachstum der Babys untersuchen will, hat ein Problem: Entscheidend ist nicht der absolute Messzeitpunkt, sondern das Alter des Babys bei der Messung. Kannst du diese Information ergänzen? So könnte es aussehen:
Tabelle 02
name
gender
age0
age1
age2
age3
age4
age5
age6
Jackson Smith
M
NA
76.69
84.91
97.06
105.73
107.32
NA
Sophia Johnson
F
NA
76.05
NA
NA
NA
NA
NA
Emma Williams
F
72.65
82.46
91.76
NA
NA
NA
NA
Aiden Jones
M
69.76
79.89
NA
NA
NA
NA
NA
Liam Brown
M
NA
NA
85.34
93.22
105.78
105.84
114.82
Lucas Davis
M
71.59
84.87
92.10
100.73
104.21
NA
NA
Olivia Miller
F
62.74
81.39
92.02
98.32
106.44
NA
NA
Ava Wilson
F
NA
NA
88.39
100.67
107.58
111.52
NA
Die Zahl der NAs ist gestiegen. ## Wide-Form-Daten Was, wenn du das Alter in Monaten abbilden willst? Dann sähe es etwa so aus:
Tabelle 03
name
gender
m4
m6
m7
m10
m12
...
m55
m60
m65
m72
Jackson Smith
M
NA
NA
NA
NA
76.69
...
NA
107.32
NA
NA
Sophia Johnson
F
NA
NA
NA
NA
76.05
...
NA
NA
NA
NA
Emma Williams
F
NA
NA
NA
72.65
NA
...
NA
NA
NA
NA
Aiden Jones
M
NA
69.76
NA
NA
NA
...
NA
NA
NA
NA
Liam Brown
M
NA
NA
NA
NA
NA
...
NA
105.84
NA
114.82
Lucas Davis
M
NA
NA
71.59
NA
NA
...
104.21
NA
NA
NA
Olivia Miller
F
62.74
NA
NA
NA
NA
...
NA
NA
NA
NA
Ava Wilson
F
NA
NA
NA
NA
NA
...
NA
NA
111.52
NA
In der Tabelle oben häufen sich die NAs. Wenn sich die relativen Messzeitpunkte der Babys unterscheiden, verschwendet die Wide-Form viel Platz. Eine Alternative wäre, das Alter der Babys für das Jahr 2015 aufzunehmen – das geht aber nur, wenn alle absoluten Messzeitpunkte identisch sind. Variieren die Zeiten um Monate und du willst das Alter in Monaten wissen, funktioniert das nicht. In so einem Fall bietet sich Long-Form an. ## Daten in Long-Form Während in der Wide-Form alle Messungen eines Babys in einer Zeile stehen, enthält die Long-Form pro Zeile genau eine Messung eines Babys. Am einfachsten: Name des Kindes, Messzeitpunkt und Messwert (Größe) in einer Zeile. Genau das zeigt diese Tabelle:
Tabelle 04
name
gender
month
height
Olivia Miller
F
4
62.74
Aiden Jones
M
6
69.76
Lucas Davis
M
7
71.59
Emma Williams
F
10
72.65
Jackson Smith
M
12
76.69
...
...
...
...
Liam Brown
M
72
114.82
Sortierst du die Daten nach Namen, erhältst du eine Tabelle wie unten. Sie braucht deutlich weniger Platz als Tabelle 3 oben.
Tabelle 05
name
gender
month
height
Jackson Smith
M
12
76.69
Jackson Smith
M
24
84.91
Jackson Smith
M
36
97.06
Jackson Smith
M
48
105.73
Jackson Smith
M
60
107.32
Sophia Johnson
F
12
76.05
Emma Williams
F
10
72.65
...
...
...
...
Ava Wilson
F
65
111.52
Long versus Wide
Merke dir noch einmal den grundlegenden Unterschied zwischen Wide- und Long-Form: In der Wide-Form stehen viele Messungen einer Person in einer Zeile und die Spaltennamen geben an, was gemessen wurde.
Diese Tabelle zeigt Liam Browns Größen in den Jahren 2011–2015 in einer Zeile:
Tabelle 06
name
gender
year2011
year2012
year2013
year2014
year2015
Liam Brown
M
88.24
96.91
101.85
108.13
112.45
In der Long-Form stehen Liam Browns Größen in einer Spalte:
Tabelle 07
name
gender
_
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Wie du siehst, ist nicht erkennbar, worauf sich die Messungen beziehen. Ergänzt du den Spaltennamen, sieht es so aus:
Tabelle 08
name
gender
year2011, 2012, 2013, 2014, 2015
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Auch das hat einen Haken: Sophia Johnsons Größe wurde 2011–2014 nicht gemessen. Wie unten zu sehen, lässt sich der Spaltenname dann nicht einheitlich setzen:
Tabelle 09
name
gender
?
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Sophia Johnson
F
76.05
Von Wide- zu Long-Form
Die Umwandlung von Wide nach Long lässt sich in Schritte zerlegen. Bevor du mehrere Messungen aus einer Zeile in eine Spalte kippst, kannst du die Tabelle so umstellen, dass jede Zeile genau eine Messung enthält. Machen wir das für diese Tabelle:
Tabelle 10
name
gender
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
72.65
82.46
91.76
NA
NA
NA
NA
Aiden Jones
M
69.76
79.89
NA
NA
NA
NA
NA
Das Ergebnis sieht dann so aus:
Tabelle 11
name
gender
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
72.65
NA
NA
NA
NA
Emma Williams
F
82.46
NA
Emma Williams
F
91.76
Aiden Jones
M
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
79.89
Bevor du die über mehrere Spalten verteilten Messwerte in einer Spalte zusammenführst, brauchst du eine zusätzliche Spalte, die angibt, um welche Messung es sich handelt – so wie hier:
Tabelle 12
name
gender
measure
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
age0
72.65
NA
NA
NA
NA
Emma Williams
F
age1
82.46
NA
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
age1
79.89
Die neue Spalte heißt oft "measure" oder "key". Du siehst oben, dass "age0", "age1", "age2", "age3", "age4", "age5" sowohl in den Spaltennamen als auch in einer Spalte vorkommen. Lässt du die Spaltennamen weg, ergibt sich Folgendes:
Tabelle 13
name
gender
measure
_
__
___
____
_____
______
_______
Emma Williams
F
age0
72.65
NA
NA
NA
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
age1
79.89
Da nun pro Zeile nur noch eine Messung steht, kannst du sie in einer Spalte sammeln – das Ergebnis:
Tabelle 14
name
gender
measure
Emma Williams
F
age0
72.65
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Gib der Messwertspalte einen sinnvollen Namen. Üblich ist „value“:
Tabelle 15
name
gender
measure
value
Emma Williams
F
age0
72.65
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Fällt dir auf, dass „age“ sich ständig wiederholt? Den wiederkehrenden Teil kannst du herauslösen – das Ergebnis:
Tabelle 16
name
gender
age
value
Emma Williams
F
0
72.65
Emma Williams
F
1
82.46
Emma Williams
F
2
91.76
Aiden Jones
M
0
69.76
Aiden Jones
M
1
79.89
Age, das sich in jeder Zeile wiederholt, ist jetzt ein Spaltenname. Den generischen Spaltennamen value kannst du präzisieren, etwa zu height. Das macht die Bedeutung eindeutig. So sieht das aus:
Tabelle 17
name
gender
age
height
Emma Williams
F
0
72.65
Emma Williams
F
1
82.46
Emma Williams
F
2
91.76
Aiden Jones
M
0
69.76
Aiden Jones
M
1
79.89
Vergleiche Tabelle 15 mit Tabelle 17: value könnte alles Mögliche sein, height ist eindeutig. Alternativ geht auch Folgendes:
Tabelle 18
name
gender
measure
value
Emma Williams
F
height.age0
72.65
Emma Williams
F
height.age1
82.46
Emma Williams
F
height.age2
91.76
Aiden Jones
M
height.age0
69.76
Aiden Jones
M
height.age1
79.89
Betrachten wir den Fall, dass verschiedene Messgrößen vorliegen. Wenn Höhe, Gewicht und BMI gemessen werden, könnte es so aussehen. Allerdings enthält die Spalte value dann Werte auf unterschiedlichen Skalen, was verwirrend sein kann. In dieser Tabelle wurde die Größe in Zentimetern, das Gewicht in Kilogramm gemessen:
Tabelle 19
name
gender
measure
value
Emma Williams
F
height
72.65
Emma Williams
F
weight
8.22
Emma Williams
F
BMI
22.60
Aiden Jones
M
height
69.76
Aiden Jones
M
weight
8.51
Bei der Umwandlung von Wide zu Long musst du also entscheiden, welche Werte in einer Spalte gesammelt werden. Danach vergibst du einen passenden Spaltennamen.
Fassen wir zusammen: Um Wide in Long umzuwandeln, musst du festlegen, welche Spalten zu einer Spalte zusammengeführt werden. Dadurch werden viele Spalten in einer gebündelt – diese braucht einen Namen. So sieht das in den nächsten Tabellen aus:
Tabelle 20
id1
id2
age0
age1
age2
Emma Williams
F
NA
82.46
91.76
Aiden Jones
M
69.76
79.89
NA
Emma Williams
F
NA
82.46
91.76
Tabelle 21
id1
id2
age0
age1
age2
Emma Williams
F
NA
Emma Williams
F
82.46
Emma Williams
F
91.76
Aiden Jones
M
69.76
Aiden Jones
M
79.89
Aiden Jones
M
NA
Emma Williams
F
NA
Emma Williams
F
82.46
Emma Williams
F
91.76
Tabelle 22
id1
id2
age_
age0
age1
age2
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabelle 23
id1
id2
age_
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabelle 24
id1
id2
key
value
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabelle 25
id1
id2
key
value
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Schau dir die Spalten id1 und id2 an. id2 identifiziert keine Person, sondern ist ein Attribut (Geschlecht). Das ist letztlich auch eine Messung. Du kannst es also noch „länger“ machen. Die längstmögliche Form besteht aus drei Spalten: id, key und value.
Tabelle 26
id
key
value
Emma Williams
gender
F
Emma Williams
age1
82.46
Emma Williams
age2
91.76
Aiden Jones
gender
F
Aiden Jones
age0
69.76
Aiden Jones
age1
79.89
Emma Williams
gender
F
Emma Williams
age1
82.46
Emma Williams
age2
91.76
Obige Tabelle zeigt die längste Form zu Tabelle 25. Aber: Verschiedene Personen können denselben Namen haben.
Dann wird die Long-Form unklar, weil id keine Person eindeutig identifiziert. Du könntest Nummern anhängen (z. B. mit make.unique() in R), aber so unterscheidest du nicht zuverlässig zwischen geändertem und ursprünglichem Namen. Stell dir vor, jemand heißt tatsächlich „John.2“!
Die naheliegende Lösung: Eine numerische ID pro Person. Dann sind Namen wiederum Messungen.
Die nächste Tabelle zeigt, dass sogar Namen als Messung betrachtet werden. In gewisser Weise ist das die „wahre“ längste Form.
Tabelle 27
id
key
value
1
name
Emma Williams
1
gender
F
1
age1
82.46
1
age2
91.76
2
name
Aiden Jones
2
gender
F
2
age0
69.76
2
age1
79.89
3
name
Emma Williams
3
gender
F
3
age1
82.46
3
age2
91.76
Die längste Form eignet sich am besten, um wieder zur Wide-Form zu wechseln. Kehre die Schritte aus den Tabellen 20 bis 25 um – so kommst du zurück zur Wide-Form. Die nächsten Tabellen zeigen den Prozess:
Tabelle 28. Messungen in der Spalte key werden in Spaltennamen zurückgeführt
id
key
name
gender
age0
age1
age2
1
name
Emma Williams
1
gender
F
1
age1
82.46
1
age2
91.76
2
name
Aiden Jones
2
gender
F
2
age0
69.76
2
age1
79.89
3
name
Emma Williams
3
gender
F
3
age1
82.46
3
age2
91.76
Tabelle 29. Spalte key kann entfernt werden
id
name
gender
age0
age1
age2
1
Emma Williams
1
F
1
82.46
1
91.76
2
Aiden Jones
2
F
2
69.76
2
79.89
3
Emma Williams
3
F
3
82.46
3
91.76
Tabelle 30. Gleiche id zu einer Zeile zusammenführen
id
name
gender
age0
age1
age2
1
Emma Williams
F
82.46
91.76
1
1
1
2
Aiden Jones
F
69.76
79.89
2
2
2
3
Emma Williams
F
82.46
91.76
3
3
3
Tabelle 31. Zeilen ohne Messwerte löschen
id
name
gender
age0
age1
age2
1
Emma Williams
F
82.46
91.76
2
Aiden Jones
F
69.76
79.89
3
Emma Williams
F
82.46
91.76
Der Schlüssel bei der Umwandlung von Wide zu Long ist die Entscheidung, welche Spalten in einer Spalte zusammengeführt werden.
Es muss dabei nicht bei einer Spalte bleiben. Du kannst auch zwei Zielspalten nutzen, wenn es sinnvoll ist – wie in dieser Tabelle:
Tabelle 32
name
gender
h2011
h2012
w2011
w2012
Jackson Smith
M
74.69
84.99
9.60
12.0
Olivia Miller
F
NA
80.76
7.15
10.7
Ava Wilson
F
88.77
96.45
NA
15.0
Kannst du das in die Long-Form bringen?
Die Spalten h2011, h2012, w2011, w2012 stehen für Größe und Gewicht in den Jahren 2011 und 2012. height und weight sind unterschiedlich skaliert (cm, kg). Du kannst sie in eine gemeinsame oder in zwei getrennte Spalten schreiben – so wie hier:
Tabelle 33
name
gender
year
height
weight
Jackson Smith
M
2011
74.69
9.60
Jackson Smith
M
2012
84.99
12.00
Olivia Miller
F
2011
NA
80.76
Olivia Miller
F
2012
7.15
10.70
Ava Wilson
F
2011
88.77
96.45
Ava Wilson
F
2012
NA
15.00
Ist das nun Long- oder Wide-Form?
Von Long zu Wide in R
Lass uns die Umwandlung zwischen Long- und Wide-Form in R durchführen. Es gibt zahlreiche Funktionen und Pakete dafür.
Tabelle 34
func
package
to_long_form
to_wide_form
stack/unstack
utils
stack
unstack
reshape
stats
reshape(direction="long", ...)
reshape(direction="wide", ...)
melt/dcast
reshape2
melt
dcast
gather/spread
tidyr
gather
spread
Hier zeige ich dir melt() und dcast() aus dem Paket reshape2. stack() und unstack() sind zwar Basisfunktionen, erfordern aber oft Nachbearbeitung. gather() und spread() aus tidyr sind ebenfalls beliebt, werden hier aber nicht behandelt.
Eine weitere Option ist reshape() aus dem Paket stats. Verwechsle die Funktion nicht mit dem Paket reshape! Dieses sowie reshape2 wurden entwickelt, um die Arbeit mit reshape() zu erleichtern. Außerdem setzt reshape() oft Längsschnittdaten voraus, also wiederholte Messungen über die Zeit.
Konvertieren wir die Daten aus Tabelle 35 in die Long-Form. Angenommen, die Tabelle ist als data.framedat gespeichert.
## name gender year2011 year2012 year2013
## 1 Jackson Smith M74.6984.9991.73
## 2 Emma Williams FNANA75.74
## 3 Liam Brown M88.24NA101.83
## 4 Ava Wilson F88.7796.45NABereitgestellt von
Die zentrale Frage lautet: „Welche Spalten sollen zu einer Spalte zusammengeführt werden?“
Das sind hier year2011, year2012, year2013. Mit melt() gibst du diese Spalten in measure.vars an:
melt(babies, measure.vars =c("year2011","year2012","year2013"))
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NABereitgestellt von
year2011, year2012, year2013 sind die Spalten 3, 4 und 5 – das kannst du auch so angeben:
melt(babies, measure.vars =3:5)
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NABereitgestellt von
Das Ergebnis siehst du oben. Beachte die Spaltennamen variable und value. In Tabelle 23 und 24 hast du gesehen, dass neue Spaltennamen nötig sind. melt() verwendet standardmäßig variable und value. Mit variable.name= und value.name= kannst du das überschreiben:
melt(babies, measure.vars=3:5, variable.name="year", value.name="height")
## name gender year height
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NABereitgestellt von
In den Beispielen oben wurden die Messungen explizit angegeben. In manchen Fällen lassen sich Messungen auch indirekt über die IDs festlegen. Dann wählst du die ID-Spalten statt der Messspalten.
Beide Varianten führen zum gleichen Ergebnis. Die erste wählt ID-Spalten, die zweite die zu sammelnden Spalten:
melt(babies, id.vars=c("name","gender"))melt(babies, measure.vars =c("year2011","year2012","year2013"))
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NABereitgestellt von
Gibst du sowohl id.vars als auch measure.vars an, werden Spalten, die in keiner der beiden Listen stehen, ausgeschlossen. Beispiel:
melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"))
## name variable value
## 1 Jackson Smith year2011 74.69
## 2 Emma Williams year2011 NA
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 6 Emma Williams year2012 NA
## 7 Liam Brown year2012 NA
## 8 Ava Wilson year2012 96.45Bereitgestellt von
Mit na.rm=T kannst du NAs entfernen:
melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"), na.rm=T)
## name variable value
## 1 Jackson Smith year2011 74.69
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8 Ava Wilson year2012 96.45Bereitgestellt von
dcast() macht das Gegenteil von melt(). Die Spalten id, variable und value bilden die längste Form. dcast(data, id ~ variable, value.var="value") bringt sie zurück in die Wide-Form.
babiesLong <-melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"), na.rm=T)
babiesLong
## name variable value
## 1 Jackson Smith year2011 74.69
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8 Ava Wilson year2012 96.45Bereitgestellt von
babiesLong enthält name als id, variable als variable und value als value. Mit dcast() stellst du wieder auf Wide um:
dcast(babiesLong, name ~ variable, value.var="value")
## name year2011 year2012
## 1 Ava Wilson 88.7796.45
## 2 Jackson Smith 74.6984.99
## 3 Liam Brown 88.24NABereitgestellt von
Fazit
Das war’s im Wesentlichen. In diesem Tutorial ging es darum, die Logik und den Prozess des Umformens von Daten zu verstehen. Für Analysen ist Long-Form meist im Vorteil, es gibt aber Ausnahmen. Zur Präsentation kann Wide-Form Platz sparen – je mehr fehlende Werte auftreten, desto eher lohnt sich die Umstellung auf Long-Form.
Für die Formatumwandlung musst du klären, was die Messungen sind. Das Motto der Long-Form lautet: eine Messung pro Zeile; in der Wide-Form stehen viele Messungen in einer Zeile. Wenn du Messungen aus mehreren Spalten in einer Spalte sammelst, müssen die ursprünglichen Spaltennamen in einer Zusatzspalte erhalten bleiben. Wenn du Messungen aus einer Spalte wieder auf Spalten verteilst, leitest du die Spaltennamen aus der Spalte variable ab.
Wenn du den Prozess verinnerlicht hast, gehen Funktionen wie dcast() und melt() leicht von der Hand!
Gewinne Vertrauen in die OLS-Regression, indem du ihre theoretischen Grundlagen beherrschst. Erforsche, wie du einfache Implementierungen in Excel, R und Python durchführst.
Mach dich mit Python-Datenstrukturen vertraut: Lerne mehr über Datentypen und primitive sowie nicht-primitive Datenstrukturen wie Strings, Listen, Stapel usw.
Lerne, wie du Zahlen in Python mit round(), f-Strings, format(), dem decimal-Modul, NumPy und mehr auf zwei Dezimalstellen rundest — inklusive Vergleichstabelle der Methoden.
Lerne, wie du Python-Listen mit Techniken wie Slicing, List Comprehensions und itertools aufteilen kannst. Finde heraus, wann du welche Methode für die beste Datenverarbeitung nutzen solltest.
Es gibt Situationen, in denen Daten vom Long-Format (was damit gemeint ist, wird gleich klar) ins Wide-Format umgewandelt werden müssen – und umgekehrt. Reale Daten liegen in den unterschiedlichsten Formaten vor, aber viele R-Funktionen sind auf eine bestimmte Form ausgelegt.
So sind etwa
lme4::lmer()für gemischte lineare Modelle oderggplot2::ggplot()für Visualisierung auf Long-Form ausgelegt. Andere Funktionen wiemosaicplot()erwarten hingegen Wide-Form. Das bedeutet: Wenn deine Daten nicht bereits passend aufbereitet sind, musst du für Analyse oder Visualisierung das Format wechseln.In R gibt es mehrere Wege für Formatumwandlungen – gerade am Anfang kann das verwirrend sein.
In diesem Tutorial lernst du die Mechanik hinter der Umwandlung zwischen Long- und Wide-Form kennen. Dich erwarten folgende Themen:
melt()unddcast()vom Long- ins Wide-Format und zurück wechselst.Die Daten
Die Tabelle zeigt die Größe von Babys in einem kleinen Einzugsgebiet. Gemessen wurde von 2011 bis 2015. Wie du sicher weißt, bedeutet
NA„Not Available“ (nicht verfügbar). Anhand der Positionen der NAs lässt sich das Alter der Babys ableiten, aber das exakte Alter ist der Tabelle nicht zu entnehmen. Die Tabelle wirkt ordentlich, doch wer das Wachstum der Babys untersuchen will, hat ein Problem: Entscheidend ist nicht der absolute Messzeitpunkt, sondern das Alter des Babys bei der Messung. Kannst du diese Information ergänzen? So könnte es aussehen:Die Zahl der
NAs ist gestiegen. ## Wide-Form-Daten Was, wenn du das Alter in Monaten abbilden willst? Dann sähe es etwa so aus:In der Tabelle oben häufen sich die
NAs. Wenn sich die relativen Messzeitpunkte der Babys unterscheiden, verschwendet die Wide-Form viel Platz. Eine Alternative wäre, das Alter der Babys für das Jahr 2015 aufzunehmen – das geht aber nur, wenn alle absoluten Messzeitpunkte identisch sind. Variieren die Zeiten um Monate und du willst das Alter in Monaten wissen, funktioniert das nicht. In so einem Fall bietet sich Long-Form an. ## Daten in Long-Form Während in der Wide-Form alle Messungen eines Babys in einer Zeile stehen, enthält die Long-Form pro Zeile genau eine Messung eines Babys. Am einfachsten: Name des Kindes, Messzeitpunkt und Messwert (Größe) in einer Zeile. Genau das zeigt diese Tabelle:Sortierst du die Daten nach Namen, erhältst du eine Tabelle wie unten. Sie braucht deutlich weniger Platz als Tabelle 3 oben.
Long versus Wide
Merke dir noch einmal den grundlegenden Unterschied zwischen Wide- und Long-Form: In der Wide-Form stehen viele Messungen einer Person in einer Zeile und die Spaltennamen geben an, was gemessen wurde.
Diese Tabelle zeigt Liam Browns Größen in den Jahren 2011–2015 in einer Zeile:
In der Long-Form stehen Liam Browns Größen in einer Spalte:
Wie du siehst, ist nicht erkennbar, worauf sich die Messungen beziehen. Ergänzt du den Spaltennamen, sieht es so aus:
Auch das hat einen Haken: Sophia Johnsons Größe wurde 2011–2014 nicht gemessen. Wie unten zu sehen, lässt sich der Spaltenname dann nicht einheitlich setzen:
Von Wide- zu Long-Form
Die Umwandlung von Wide nach Long lässt sich in Schritte zerlegen. Bevor du mehrere Messungen aus einer Zeile in eine Spalte kippst, kannst du die Tabelle so umstellen, dass jede Zeile genau eine Messung enthält. Machen wir das für diese Tabelle:
Das Ergebnis sieht dann so aus:
Bevor du die über mehrere Spalten verteilten Messwerte in einer Spalte zusammenführst, brauchst du eine zusätzliche Spalte, die angibt, um welche Messung es sich handelt – so wie hier:
Die neue Spalte heißt oft
"measure"oder"key". Du siehst oben, dass"age0","age1","age2","age3","age4","age5"sowohl in den Spaltennamen als auch in einer Spalte vorkommen. Lässt du die Spaltennamen weg, ergibt sich Folgendes:Da nun pro Zeile nur noch eine Messung steht, kannst du sie in einer Spalte sammeln – das Ergebnis:
Gib der Messwertspalte einen sinnvollen Namen. Üblich ist „value“:
Fällt dir auf, dass „age“ sich ständig wiederholt? Den wiederkehrenden Teil kannst du herauslösen – das Ergebnis:
Age, das sich in jeder Zeile wiederholt, ist jetzt ein Spaltenname. Den generischen Spaltennamenvaluekannst du präzisieren, etwa zuheight. Das macht die Bedeutung eindeutig. So sieht das aus:Vergleiche Tabelle 15 mit Tabelle 17:
valuekönnte alles Mögliche sein,heightist eindeutig. Alternativ geht auch Folgendes:Betrachten wir den Fall, dass verschiedene Messgrößen vorliegen. Wenn Höhe, Gewicht und BMI gemessen werden, könnte es so aussehen. Allerdings enthält die Spalte
valuedann Werte auf unterschiedlichen Skalen, was verwirrend sein kann. In dieser Tabelle wurde die Größe in Zentimetern, das Gewicht in Kilogramm gemessen:Bei der Umwandlung von Wide zu Long musst du also entscheiden, welche Werte in einer Spalte gesammelt werden. Danach vergibst du einen passenden Spaltennamen.
Fassen wir zusammen: Um Wide in Long umzuwandeln, musst du festlegen, welche Spalten zu einer Spalte zusammengeführt werden. Dadurch werden viele Spalten in einer gebündelt – diese braucht einen Namen. So sieht das in den nächsten Tabellen aus:
Schau dir die Spalten
id1undid2an.id2identifiziert keine Person, sondern ist ein Attribut (Geschlecht). Das ist letztlich auch eine Messung. Du kannst es also noch „länger“ machen. Die längstmögliche Form besteht aus drei Spalten:id,keyundvalue.Obige Tabelle zeigt die längste Form zu Tabelle 25. Aber: Verschiedene Personen können denselben Namen haben.
Dann wird die Long-Form unklar, weil
idkeine Person eindeutig identifiziert. Du könntest Nummern anhängen (z. B. mitmake.unique()in R), aber so unterscheidest du nicht zuverlässig zwischen geändertem und ursprünglichem Namen. Stell dir vor, jemand heißt tatsächlich „John.2“!Die naheliegende Lösung: Eine numerische ID pro Person. Dann sind Namen wiederum Messungen.
Die nächste Tabelle zeigt, dass sogar Namen als Messung betrachtet werden. In gewisser Weise ist das die „wahre“ längste Form.
Die längste Form eignet sich am besten, um wieder zur Wide-Form zu wechseln. Kehre die Schritte aus den Tabellen 20 bis 25 um – so kommst du zurück zur Wide-Form. Die nächsten Tabellen zeigen den Prozess:
Der Schlüssel bei der Umwandlung von Wide zu Long ist die Entscheidung, welche Spalten in einer Spalte zusammengeführt werden.
Es muss dabei nicht bei einer Spalte bleiben. Du kannst auch zwei Zielspalten nutzen, wenn es sinnvoll ist – wie in dieser Tabelle:
Kannst du das in die Long-Form bringen?
Die Spalten
h2011,h2012,w2011,w2012stehen für Größe und Gewicht in den Jahren 2011 und 2012.heightundweightsind unterschiedlich skaliert (cm, kg). Du kannst sie in eine gemeinsame oder in zwei getrennte Spalten schreiben – so wie hier:Ist das nun Long- oder Wide-Form?
Von Long zu Wide in R
Lass uns die Umwandlung zwischen Long- und Wide-Form in R durchführen. Es gibt zahlreiche Funktionen und Pakete dafür.
Hier zeige ich dir
melt()unddcast()aus dem Paketreshape2.stack()undunstack()sind zwar Basisfunktionen, erfordern aber oft Nachbearbeitung.gather()undspread()austidyrsind ebenfalls beliebt, werden hier aber nicht behandelt.Eine weitere Option ist
reshape()aus dem Paketstats. Verwechsle die Funktion nicht mit dem Paketreshape! Dieses sowiereshape2wurden entwickelt, um die Arbeit mitreshape()zu erleichtern. Außerdem setztreshape()oft Längsschnittdaten voraus, also wiederholte Messungen über die Zeit.Konvertieren wir die Daten aus Tabelle 35 in die Long-Form. Angenommen, die Tabelle ist als
data.framedatgespeichert.babies = data.frame(name= c("Jackson Smith", "Emma Williams", "Liam Brown", "Ava Wilson"), gender = c("M", "F", "M", "F"), year2011= c(74.69, NA, 88.24, 88.77), year2012=c(84.99, NA, NA, 96.45), year2013=c(91.73, 75.74, 101.83, NA)) babies
Die zentrale Frage lautet: „Welche Spalten sollen zu einer Spalte zusammengeführt werden?“
Das sind hier
year2011,year2012,year2013. Mitmelt()gibst du diese Spalten inmeasure.varsan:year2011,year2012,year2013sind die Spalten 3, 4 und 5 – das kannst du auch so angeben:Das Ergebnis siehst du oben. Beachte die Spaltennamen
variableundvalue. In Tabelle 23 und 24 hast du gesehen, dass neue Spaltennamen nötig sind.melt()verwendet standardmäßigvariableundvalue. Mitvariable.name=undvalue.name=kannst du das überschreiben:In den Beispielen oben wurden die Messungen explizit angegeben. In manchen Fällen lassen sich Messungen auch indirekt über die IDs festlegen. Dann wählst du die ID-Spalten statt der Messspalten.
Beide Varianten führen zum gleichen Ergebnis. Die erste wählt ID-Spalten, die zweite die zu sammelnden Spalten:
Gibst du sowohl
id.varsals auchmeasure.varsan, werden Spalten, die in keiner der beiden Listen stehen, ausgeschlossen. Beispiel:Mit
na.rm=Tkannst du NAs entfernen:dcast()macht das Gegenteil vonmelt(). Die Spaltenid,variableundvaluebilden die längste Form.dcast(data, id ~ variable, value.var="value")bringt sie zurück in die Wide-Form.babiesLongenthältnamealsid,variablealsvariableundvaluealsvalue. Mitdcast()stellst du wieder auf Wide um:Fazit
Das war’s im Wesentlichen. In diesem Tutorial ging es darum, die Logik und den Prozess des Umformens von Daten zu verstehen. Für Analysen ist Long-Form meist im Vorteil, es gibt aber Ausnahmen. Zur Präsentation kann Wide-Form Platz sparen – je mehr fehlende Werte auftreten, desto eher lohnt sich die Umstellung auf Long-Form.
Für die Formatumwandlung musst du klären, was die Messungen sind. Das Motto der Long-Form lautet: eine Messung pro Zeile; in der Wide-Form stehen viele Messungen in einer Zeile. Wenn du Messungen aus mehreren Spalten in einer Spalte sammelst, müssen die ursprünglichen Spaltennamen in einer Zusatzspalte erhalten bleiben. Wenn du Messungen aus einer Spalte wieder auf Spalten verteilst, leitest du die Spaltennamen aus der Spalte
variableab.Wenn du den Prozess verinnerlicht hast, gehen Funktionen wie
dcast()undmelt()leicht von der Hand!