Sök…


Anmärkningar

Den officiella vinjetten, "Effektiv omformning med data.tabeller" , är den bästa introduktionen till detta ämne.

Många omformningsuppgifter kräver att du flyttar mellan långa och breda format:

  • Bred data är data med varje kolumn som representerar en separat variabel och rader som representerar separata observationer
  • Långa data är data med formen ID | variabel | värde, där varje rad representerar ett observationsvariabelt par

smälta och gjutas med data.table

data.table erbjuder ett brett utbud av möjligheter att omforma dina data både effektivt och enkelt

När du till exempel omformar från lång till bred kan du både skicka flera variabler till value.var och till fun.aggregate parametrarna på samma gång

library(data.table) #v>=1.9.6
DT <- data.table(mtcars)

Lång till bred

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

Detta ställer in gear som indexkolumn, medan mean och sum kommer att beräknas för disp och hp för varje gear och cyl . Om det inte finns några kombinationer kan du ange ytterligare parametrar som na.rm = TRUE (som kommer att skickas till mean och sum ) eller specificera det inbyggda fill . Du kan också lägga till marginaler, släppa kombinationer som saknas och dela upp data. Se mer i ?data.table::dcast


Bred till lång

När du omformar från brett till lång kan du till exempel överföra kolumner till parametern measure.vars med vanliga uttryck

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

Detta kommer att melt data med cyl och gear som indexkolumner, medan alla värden för variablerna som börjar med d ( disp & drat ) kommer att finnas i value1 och värdena för variablerna som innehåller bokstaven e i dem ( qsec och gear ) kommer att finnas i value2 kolumnen.

Du kan också byta namn på alla kolumnnamn i resultatet medan du specificerar variable.name och value.name eller besluta om du vill att character automatiskt ska konverteras till factor s eller inte medan du specificerar variable.factor och value.factor . Se mer i ?data.table::melt

Omforma med "data.table"

data.table förlänger reshape2 melt och dcast

( Referens: Effektiv omformning med data.tabeller )

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

Lång till bred

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

På flera kolumner (från 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

Bred till lång

## 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

Går från brett till långt format med smält

Smältning: Grunderna

Smältning används för att omvandla data från brett till långt format.

Börjar med en bred datauppsättning:

DT = data.table(ID = letters[1:3], Age = 20:22, OB_A = 1:3, OB_B = 4:6, OB_C = 7:9)

Vi kan smälta våra data med hjälp av melt funktion data.table. Detta returnerar en annan data.table i långt format:

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"

Alla kolumner som inte är inställda i parametern id.vars antas vara variabler. Alternativt kan vi ställa in dessa uttryckligen med hjälp av argumentet 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

I det här fallet antas alla kolumner som inte är inställda i measure.vars vara ID: er.

Om vi ställer in båda uttryckligen kommer det bara att returnera de valda kolumnerna:

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

Namnge variabler och värden i resultatet

Vi kan manipulera kolumnnamnen i den returnerade tabellen med variable.name och 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

Ställa in typer för mätvariabler i resultatet

Som standard konverterar alla measure.vars till att smälta en measure.vars till faktorer:

M_DT <- melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"))
class(M_DT[, variable])
# "factor"

För att ställa in som tecken istället använder du variable.factor argumentet:

M_DT <- melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"), variable.factor = FALSE)
class(M_DT[, variable])
# "character"

Värden ärver vanligtvis från datatypen för den ursprungliga kolumnen:

class(DT[, value])
# "integer"
class(M_DT[, value])
# "integer"

Om det är en konflikt tvingas datatyper. Till exempel:

M_DT <- melt(DT,id.vars = c("Age"), measure.vars = c("ID","OB_C"))
class(M_DT[, value])
# "character"

Vid smältning tvingas alla faktorvariabler till karaktärstyp:

DT[, OB_C := factor(OB_C)]
M_DT <- melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"))
class(M_DT)
# "character"

value.factor argumentet value.factor att undvika detta och bevara den första value.factor

M_DT <- melt(DT,id.vars = c("ID"), measure.vars = c("OB_C"), value.factor = TRUE)
class(M_DT)
# "factor"

Hantering av saknade värden

Som standard bevaras alla NA värden i smält data

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

Om dessa bör tas bort från dina data, ställ in 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

Går från långt till brett format med hjälp av dcast

Gjutning: Grunderna

Gjutning används för att omvandla data från långt till brett format.

Börjar med en lång datauppsättning:

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)

Vi kan kasta våra data med hjälp av dcast funktionen i data.table. Detta returnerar en annan data.table i brett format:

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"

Gjutning av ett värde

Ett value.var argument är nödvändigt för en korrekt roll - om inte meddelandet kommer dcast att göra ett antagande baserat på dina data.

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

Flera value.var kan anges i en lista

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

Gjutning styrs med dcast i dcast . Detta är av formen 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

Både rader och kolumner kan utökas med ytterligare variabler med +

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

Gjutning kan ofta skapa celler där ingen observation finns i data. Som standard betecknas detta av NA , som ovan. Vi kan åsidosätta detta med fill= -argumentet.

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

Du kan också använda två specialvariabler i formelobjektet

  • . representerar inga andra variabler
  • ... representerar alla andra variabler
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

Samla vårt värde.var

Vi kan också casta och aggregera värden i ett steg. I det här fallet har vi tre observationer i vart och ett av korsningarna mellan ålder och ID. För att ange vilken aggregering vi vill använda, använder fun.aggregate argumentet 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

Vi kan också skicka en lista till fun.aggregate att använda flera funktioner

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

Om vi passerar mer än en funktion och mer än ett värde kan vi beräkna alla kombinationer genom att passera en vektor med värde.vars

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

där varje par beräknas i ordningsvärdet1_formel1 value1_formula1, value1_formula2, ... , valueN_formula(N-1), valueN_formulaN .

Alternativt kan vi utvärdera våra värden och funktioner en-till-en genom att lämna 'value.var' som en lista:

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

Namnge kolumner i resultatet

Som standard separeras kolumnnamnskomponenter av en understruk _ . Detta kan åsidosättas manuellt med sep= argumentet:

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

Detta fun.aggregate alla fun.aggregate eller value.var vi använder:

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

Stapla flera tabeller med rbindlist

En vanlig refrain i R går enligt dessa linjer:

Du bör inte ha ett gäng relaterade tabeller med namn som DT1 , DT2 , ..., DT11 . Iterativt läsning och tilldelning till objekt med namn är rörigt. Lösningen är en lista med datatabeller!

En sådan lista ser ut

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

Ett annat perspektiv är att du ska lagra dessa tabeller tillsammans som ett bord genom att stapla dem. Detta är enkelt att göra med rbindlist :

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

Detta format är mycket mer meningsfullt med data.table-syntax, där "per grupp" -operationer är vanliga och enkla.

För en djupare titt kan Gregors svar vara ett bra ställe att börja. Kolla ?rbindlist också ut ?rbindlist . Det finns ett separat exempel som täcker läsning i en massa tabeller från CSV och sedan staplar dem .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow