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 .



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow