data.table
Umformen, Stapeln und Spalten
Suche…
Bemerkungen
Die offizielle Vignette "Effiziente Umgestaltung mit data.tables" ist die beste Einführung in dieses Thema.
Viele Umformungsaufgaben erfordern den Wechsel zwischen langen und breiten Formaten:
- Breite Daten sind Daten, wobei jede Spalte eine separate Variable darstellt und die Zeilen getrennte Beobachtungen darstellen
- Lange Daten sind Daten mit der Formular-ID | Variable | Wert, wobei jede Zeile ein Beobachtungsvariablenpaar darstellt
schmelzen und gießen mit data.table
data.table
bietet eine Vielzahl von Möglichkeiten, um Ihre Daten effizient und einfach umzugestalten
Beim Umformen von "long" in "wide" können Sie beispielsweise mehrere Variablen gleichzeitig in die value.var
und in die fun.aggregate
-Parameter übergeben
library(data.table) #v>=1.9.6
DT <- data.table(mtcars)
Lang bis breit
dcast(DT, gear ~ cyl, value.var = c("disp", "hp"), fun = list(mean, sum))
gear disp_mean_4 disp_mean_6 disp_mean_8 hp_mean_4 hp_mean_6 hp_mean_8 disp_sum_4 disp_sum_6 disp_sum_8 hp_sum_4 hp_sum_6 hp_sum_8
1: 3 120.100 241.5 357.6167 97 107.5 194.1667 120.1 483.0 4291.4 97 215 2330
2: 4 102.625 163.8 NaN 76 116.5 NaN 821.0 655.2 0.0 608 466 0
3: 5 107.700 145.0 326.0000 102 175.0 299.5000 215.4 145.0 652.0 204 175 599
Dadurch wird der gear
als disp
, während mean
und sum
für disp
und hp
für jede Kombination aus gear
und cyl
berechnet werden. Für den Fall , einige Kombinationen sind nicht vorhanden Sie zusätzliche Parameter wie angeben könnten na.rm = TRUE
(die weitergegeben werden mean
und sum
oder das eingebaute angeben fill
Argument. Sie können auch Ränder hinzufügen, fehlende Kombinationen löschen und die Daten subsetieren. Mehr dazu in ?data.table::dcast
Weit bis lang
Bei der Umformung von "Breit" in "Lang" können Sie Spalten mit regulären Ausdrücken an den Parameter " measure.vars
print(melt(DT, c("cyl", "gear"), measure = patterns("^d", "e")), n = 10)
cyl gear variable value1 value2
1: 6 4 1 160.00 16.46
2: 6 4 1 160.00 17.02
3: 4 4 1 108.00 18.61
4: 6 3 1 258.00 19.44
5: 8 3 1 360.00 17.02
---
60: 4 5 2 3.77 5.00
61: 8 5 2 4.22 5.00
62: 6 5 2 3.62 5.00
63: 8 5 2 3.54 5.00
64: 4 4 2 4.11 4.00
Dies wird melt
die Daten durch cyl
und gear
wie die Indexspalten, während alle Werte für die Variablen , die mit beginnen d
( disp
& drat
in sein vorhanden) value1
und die Werte für die Variablen, die den Buchstaben enthalten e
in ihnen ( qsec
und gear
) werden in der Spalte von value2
angezeigt.
Sie können auch alle Spaltennamen im Ergebnis umbenennen, während value.name
Argumente variable.name
und value.name
, oder entscheiden, ob die character
automatisch in den factor
s konvertiert werden sollen oder nicht, während value.factor
Argumente variable.factor
und value.factor
. Mehr dazu in ?data.table::melt
Umformen mit `data.table`
data.table
erstreckt reshape2
‚s melt
& dcast
Funktionen
( Referenz: Effizientes Umformen mit data.tables )
library(data.table)
## generate some data
dt <- data.table(
name = rep(c("firstName", "secondName"), each=4),
numbers = rep(1:4, 2),
value = rnorm(8)
)
dt
# name numbers value
# 1: firstName 1 -0.8551881
# 2: firstName 2 -1.0561946
# 3: firstName 3 0.2671833
# 4: firstName 4 1.0662379
# 5: secondName 1 -0.4771341
# 6: secondName 2 1.2830651
# 7: secondName 3 -0.6989682
# 8: secondName 4 -0.6592184
Lang bis breit
dcast(data = dt,
formula = name ~ numbers,
value.var = "value")
# name 1 2 3 4
# 1: firstName 0.1836433 -0.8356286 1.5952808 0.3295078
# 2: secondName -0.8204684 0.4874291 0.7383247 0.5757814
Auf mehreren Spalten (ab data.table
1.9.6)
## add an extra column
dt[, value2 := value * 2]
## cast multiple value columns
dcast(data = dt,
formula = name ~ numbers,
value.var = c("value", "value2"))
# name value_1 value_2 value_3 value_4 value2_1 value2_2 value2_3 value2_4
# 1: firstName 0.1836433 -0.8356286 1.5952808 0.3295078 0.3672866 -1.6712572 3.190562 0.6590155
# 2: secondName -0.8204684 0.4874291 0.7383247 0.5757814 -1.6409368 0.9748581 1.476649 1.1515627
Weit bis lang
## use a wide data.table
dt <- fread("name 1 2 3 4
firstName 0.1836433 -0.8356286 1.5952808 0.3295078
secondName -0.8204684 0.4874291 0.7383247 0.5757814", header = T)
dt
# name 1 2 3 4
# 1: firstName 0.1836433 -0.8356286 1.5952808 0.3295078
# 2: secondName -0.8204684 0.4874291 0.7383247 0.5757814
## melt to long, specifying the id column, and the name of the columns
## in the resulting long data.table
melt(dt,
id.vars = "name",
variable.name = "numbers",
value.name = "myValue")
# name numbers myValue
# 1: firstName 1 0.1836433
# 2: secondName 1 -0.8204684
# 3: firstName 2 -0.8356286
# 4: secondName 2 0.4874291
# 5: firstName 3 1.5952808
# 6: secondName 3 0.7383247
# 7: firstName 4 0.3295078
# 8: secondName 4 0.5757814
Mit Schmelze vom breiten zum langen Format wechseln
Schmelzen: Die Grundlagen
Beim Schmelzen werden Daten vom breiten in das lange Format umgewandelt.
Beginnend mit einem breiten Datensatz:
DT = data.table(ID = letters[1:3], Age = 20:22, OB_A = 1:3, OB_B = 4:6, OB_C = 7:9)
Wir können unsere Daten mit der melt
in data.table melt
. Dies gibt eine andere data.table im langen Format zurück:
melt(DT, id.vars = c("ID","Age"))
1: a 20 OB_A 1
2: b 21 OB_A 2
3: c 22 OB_A 3
4: a 20 OB_B 4
5: b 21 OB_B 5
6: c 22 OB_B 6
7: a 20 OB_C 7
8: b 21 OB_C 8
9: c 22 OB_C 9
class(melt(DT, id.vars = c("ID","Age")))
# "data.table" "data.frame"
Alle Spalten, die nicht im Parameter id.vars
sind, werden als Variablen betrachtet. Alternativ können wir diese explizit mit dem Argument measure.vars
:
melt(DT, measure.vars = c("OB_A","OB_B","OB_C"))
ID Age variable value
1: a 20 OB_A 1
2: b 21 OB_A 2
3: c 22 OB_A 3
4: a 20 OB_B 4
5: b 21 OB_B 5
6: c 22 OB_B 6
7: a 20 OB_C 7
8: b 21 OB_C 8
9: c 22 OB_C 9
In diesem Fall wird davon ausgegangen, dass Spalten, die nicht in measure.vars
sind, IDs sind.
Wenn wir beide explizit festlegen, werden nur die ausgewählten Spalten zurückgegeben:
melt(DT, id.vars = "ID", measure.vars = c("OB_C"))
ID variable value
1: a OB_C 7
2: b OB_C 8
3: c OB_C 9
Variablen und Werte im Ergebnis benennen
Wir können die Spaltennamen der zurückgegebenen Tabelle mithilfe von variable.name
und value.name
melt(DT,
id.vars = c("ID"),
measure.vars = c("OB_C"),
variable.name = "Test",
value.name = "Result"
)
ID Test Result
1: a OB_C 7
2: b OB_C 8
3: c OB_C 9
Einstellungsarten für Messgrößen im Ergebnis
Beim Schmelzen einer data.table werden standardmäßig alle measure.vars
Faktoren in Faktoren konvertiert:
M_DT <- melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"))
class(M_DT[, variable])
# "factor"
Um stattdessen als Zeichen festzulegen, verwenden Sie das Argument variable.factor
:
M_DT <- melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"), variable.factor = FALSE)
class(M_DT[, variable])
# "character"
Werte erben im Allgemeinen vom Datentyp der Ursprungsspalte:
class(DT[, value])
# "integer"
class(M_DT[, value])
# "integer"
Wenn es einen Konflikt gibt, werden die Datentypen erzwungen. Zum Beispiel:
M_DT <- melt(DT,id.vars = c("Age"), measure.vars = c("ID","OB_C"))
class(M_DT[, value])
# "character"
Beim Schmelzen werden alle Faktorvariablen zum Zeichentyp gezwungen:
DT[, OB_C := factor(OB_C)]
M_DT <- melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"))
class(M_DT)
# "character"
Um dies zu vermeiden und die ursprüngliche Eingabe value.factor
, verwenden Sie das Argument value.factor
:
M_DT <- melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"), value.factor = TRUE)
class(M_DT)
# "factor"
Umgang mit fehlenden Werten
Standardmäßig werden alle NA
Werte in den geschmolzenen Daten beibehalten
DT = data.table(ID = letters[1:3], Age = 20:22, OB_A = 1:3, OB_B = 4:6, OB_C = c(7:8,NA))
melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"))
ID variable value
1: a OB_C 7
2: b OB_C 8
3: c OB_C NA
Wenn diese aus Ihren Daten entfernt werden sollen, setzen Sie na.rm = TRUE
melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"), na.rm = TRUE)
ID variable value
1: a OB_C 7
2: b OB_C 8
Mit dcast vom langen zum breiten Format wechseln
Casting: Die Grundlagen
Das Casting wird verwendet, um Daten vom langen in das große Format umzuwandeln.
Beginnend mit einem langen Datensatz:
DT = data.table(ID = rep(letters[1:3],3), Age = rep(20:22,3), Test = rep(c("OB_A","OB_B","OB_C"), each = 3), Result = 1:9)
Wir können unsere Daten mit der dcast
Funktion in data.table umwandeln. Dies gibt eine andere data.table im Breitformat zurück:
dcast(DT, formula = ID ~ Test, value.var = "Result")
ID OB_A OB_B OB_C
1: a 1 4 7
2: b 2 5 8
3: c 3 6 9
class(dcast(DT, formula = ID ~ Test, value.var = "Result"))
[1] "data.table" "data.frame"
Einen Wert abgeben
Ein value.var
Argument ist für eine ordnungsgemäße value.var
erforderlich. Wenn nicht angegeben, nimmt dcast eine auf Ihren Daten basierende Annahme vor.
dcast(DT, formula = ID ~ Test, value.var = "Result")
ID OB_A OB_B OB_C
1: a 1 4 7
2: b 2 5 8
3: c 3 6 9
ID OB_A OB_B OB_C
1: a 20 20 20
2: b 21 21 21
3: c 22 22 22
Mehrere value.var
können in einer Liste bereitgestellt werden
dcast(DT, formula = ID ~ Test, value.var = list("Result","Age"))
ID Result_OB_A Result_OB_B Result_OB_C Age_OB_A Age_OB_B Age_OB_C
1: a 1 4 7 20 20 20
2: b 2 5 8 21 21 21
3: c 3 6 9 22 22 22
Formel
Das Casting wird mit dem dcast
in dcast
. Dies ist von der Form ROWS ~ COLUMNS
dcast(DT, formula = ID ~ Test, value.var = "Result")
ID OB_A OB_B OB_C
1: a 1 4 7
2: b 2 5 8
3: c 3 6 9
dcast(DT, formula = Test ~ ID, value.var = "Result")
Test a b c
1: OB_A 1 2 3
2: OB_B 4 5 6
3: OB_C 7 8 9
Sowohl Zeilen als auch Spalten können mit +
um weitere Variablen erweitert werden
dcast(DT, formula = ID + Age ~ Test, value.var = "Result")
ID Age OB_A OB_B OB_C
1: a 20 1 4 7
2: b 21 2 5 8
3: c 22 3 6 9
dcast(DT, formula = ID ~ Age + Test, value.var = "Result")
ID 20_OB_A 20_OB_B 20_OB_C 21_OB_A 21_OB_B 21_OB_C 22_OB_A 22_OB_B 22_OB_C
1: a 1 4 7 NA NA NA NA NA NA
2: b NA NA NA 2 5 8 NA NA NA
3: c NA NA NA NA NA NA 3 6 9
#order is important
dcast(DT, formula = ID ~ Test + Age, value.var = "Result")
ID OB_A_20 OB_A_21 OB_A_22 OB_B_20 OB_B_21 OB_B_22 OB_C_20 OB_C_21 OB_C_22
1: a 1 NA NA 4 NA NA 7 NA NA
2: b NA 2 NA NA 5 NA NA 8 NA
3: c NA NA 3 NA NA 6 NA NA 9
Beim Casting können häufig Zellen erstellt werden, in denen keine Beobachtung in den Daten vorhanden ist. Standardmäßig wird dies wie oben mit NA
bezeichnet. Wir können dies mit dem Argument fill=
überschreiben.
dcast(DT, formula = ID ~ Test + Age, value.var = "Result", fill = 0)
ID OB_A_20 OB_A_21 OB_A_22 OB_B_20 OB_B_21 OB_B_22 OB_C_20 OB_C_21 OB_C_22
1: a 1 0 0 4 0 0 7 0 0
2: b 0 2 0 0 5 0 0 8 0
3: c 0 0 3 0 0 6 0 0 9
Sie können auch zwei spezielle Variablen im Formelobjekt verwenden
-
.
repräsentiert keine anderen Variablen -
...
repräsentiert alle anderen Variablen
dcast(DT, formula = Age ~ ., value.var = "Result")
Age .
1: 20 3
2: 21 3
3: 22 3
dcast(DT, formula = ID + Age ~ ..., value.var = "Result")
ID Age OB_A OB_B OB_C
1: a 20 1 4 7
2: b 21 2 5 8
3: c 22 3 6 9
Aggregation unserer value.var
Wir können Werte auch in einem Schritt umwandeln und aggregieren. In diesem Fall haben wir drei Beobachtungen an jedem Schnittpunkt von Alter und ID. Um fun.aggregate
, welche Aggregation wir wollen, verwenden wir das Argument fun.aggregate
:
#length
dcast(DT, formula = ID ~ Age, value.var = "Result", fun.aggregate = length)
ID 20 21 22
1: a 3 0 0
2: b 0 3 0
3: c 0 0 3
#sum
dcast(DT, formula = ID ~ Age, value.var = "Result", fun.aggregate = sum)
ID 20 21 22
1: a 12 0 0
2: b 0 15 0
3: c 0 0 18
#concatenate
dcast(DT, formula = ID ~ Age, value.var = "Result", fun.aggregate = function(x){paste(x,collapse = "_")})
ID 20 21 22
1: a 1_4_7
2: b 2_5_8
3: c 3_6_9
Wir können auch eine Liste an fun.aggregate
, um mehrere Funktionen zu verwenden
dcast(DT, formula = ID ~ Age, value.var = "Result", fun.aggregate = list(sum,length))
ID Result_sum_20 Result_sum_21 Result_sum_22 Result_length_20 Result_length_21 Result_length_22
1: a 12 0 0 3 0 0
2: b 0 15 0 0 3 0
3: c 0 0 18 0 0 3
Wenn wir mehr als eine Funktion und mehr als einen Wert übergeben, können wir alle Kombinationen berechnen, indem Sie einen Vektor von value.vars übergeben
dcast(DT, formula = ID ~ Age, value.var = c("Result","Test"), fun.aggregate = list(function(x){paste0(x,collapse = "_")},length))
ID Result_function_20 Result_function_21 Result_function_22 Test_function_20 Test_function_21 Test_function_22 Result_length_20 Result_length_21
1: a 1_4_7 OB_A_OB_B_OB_C 3 0
2: b 2_5_8 OB_A_OB_B_OB_C 0 3
3: c 3_6_9 OB_A_OB_B_OB_C 0 0
Result_length_22 Test_length_20 Test_length_21 Test_length_22
1: 0 3 0 0
2: 0 0 3 0
3: 3 0 0 3
wobei jedes Paar in der Reihenfolge value1_formula1, value1_formula2, ... , valueN_formula(N-1), valueN_formulaN
berechnet wird value1_formula1, value1_formula2, ... , valueN_formula(N-1), valueN_formulaN
.
Alternativ können wir unsere Werte und Funktionen eins zu eins auswerten, indem Sie 'value.var' als Liste übergeben:
dcast(DT, formula = ID ~ Age, value.var = list("Result","Test"), fun.aggregate = list(function(x){paste0(x,collapse = "_")},length))
ID Result_function_20 Result_function_21 Result_function_22 Test_length_20 Test_length_21 Test_length_22
1: a 1_4_7 3 0 0
2: b 2_5_8 0 3 0
3: c 3_6_9 0 0 3
Spalten im Ergebnis benennen
Standardmäßig werden Spaltennamenkomponenten durch einen Unterstrich _
. Dies kann manuell mit dem Argument sep=
überschrieben werden:
dcast(DT, formula = Test ~ ID + Age, value.var = "Result")
Test a_20 b_21 c_22
1: OB_A 1 2 3
2: OB_B 4 5 6
3: OB_C 7 8 9
dcast(DT, formula = Test ~ ID + Age, value.var = "Result", sep = ",")
Test a,20 b,21 c,22
1: OB_A 1 2 3
2: OB_B 4 5 6
3: OB_C 7 8 9
Dadurch werden alle von uns verwendeten fun.aggregate
oder value.var
:
dcast(DT, formula = Test ~ ID + Age, value.var = "Result", fun.aggregate = c(sum,length), sep = ",")
Test Result,sum,a,20 Result,sum,b,21 Result,sum,c,22 Result,length,a,20 Result,length,b,21 Result,length,c,22
1: OB_A 1 2 3 1 1 1
2: OB_B 4 5 6 1 1 1
3: OB_C 7 8 9 1 1 1
Mehrere Tabellen mit rbindlist stapeln
Ein gemeinsamer Refrain in R geht in diese Richtung:
Sie sollten keine verwandten Tabellen mit Namen wie
DT1
,DT2
, ...,DT11
. Das wiederholte Lesen und Zuweisen von Objekten nach Namen ist unordentlich. Die Lösung ist eine Liste von Datentabellen!
So eine Liste sieht aus
set.seed(1)
DT_list = lapply(setNames(1:3, paste0("D", 1:3)), function(i)
data.table(id = 1:2, v = sample(letters, 2)))
$D1
id v
1: 1 g
2: 2 j
$D2
id v
1: 1 o
2: 2 w
$D3
id v
1: 1 f
2: 2 w
Eine andere Perspektive ist, dass Sie diese Tabellen zusammen als eine Tabelle speichern sollten, indem Sie sie stapeln. Dies ist einfach mit rbindlist
zu tun:
DT = rbindlist(DT_list, id="src")
src id v
1: D1 1 g
2: D1 2 j
3: D2 1 o
4: D2 2 w
5: D3 1 f
6: D3 2 w
Dieses Format ist mit der Syntax data.table viel sinnvoller, wobei Operationen "nach Gruppe" häufig und unkompliziert sind.
Für einen tieferen Blick könnte Gregors Antwort ein guter Anfang sein. ?rbindlist
Sie sich auch die ?rbindlist
an. Es gibt ein separates Beispiel, in dem mehrere CSV-Tabellen gelesen und dann gestapelt werden .