Zoeken…


Opmerkingen

Het officiële vignet, "Efficiënt hervormen met behulp van data.tables" , is de beste inleiding tot dit onderwerp.

Voor veel hervormtaken moet u schakelen tussen lange en brede formaten:

  • Brede gegevens zijn gegevens waarbij elke kolom een afzonderlijke variabele vertegenwoordigt en rijen die afzonderlijke waarnemingen vertegenwoordigen
  • Lange gegevens zijn gegevens met de formulier-ID | variabele | waarde, waarbij elke rij een observatie-variabel paar vertegenwoordigt

smelt en gegoten met data.table

data.table biedt een breed scala aan mogelijkheden om uw gegevens zowel efficiënt als gemakkelijk te hervormen

Wanneer u bijvoorbeeld van lang naar breed verandert, kunt u beide verschillende variabelen tegelijkertijd doorgeven aan de parameters value.var en fun.aggregate

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

Lang tot breed

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

Hiermee wordt de gear ingesteld als de indexkolom, terwijl het mean en de sum worden berekend voor disp en hp voor elke combinatie van gear en cyl . In het geval dat sommige combinaties bestaan niet kon je extra parameters zoals een specificatie van na.rm = TRUE (die zal worden doorgegeven aan mean en sum functies) of geef de ingebouwde fill argument. U kunt ook marges toevoegen, ontbrekende combinaties verwijderen en de gegevens subset. Zie meer in ?data.table::dcast


Breed tot lang

Tijdens het omvormen van breed naar lang, kunt u kolommen doorgeven aan de parameter measure.vars met behulp van bijvoorbeeld reguliere expressies

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

Hierdoor worden de gegevens van cyl en gear melt als de drat , terwijl alle waarden voor de variabelen die beginnen met d ( disp & drat ) aanwezig zijn in value1 en de waarden voor de variabelen die de letter e erin bevatten ( qsec en gear ) zullen aanwezig zijn in de value2 kolom.

U kunt ook de naam van alle kolomnamen de in het resultaat, terwijl het opgeven van variable.name en value.name argumenten of beslissen of u wilt dat het character kolommen automatisch worden omgezet naar factor is of niet, terwijl het opgeven van variable.factor en value.factor argumenten. Zie meer in ?data.table::melt

Wijzig de vorm met `data.table`

data.table breidt reshape2 's melt & dcast functies

( Referentie: efficiënt hervormen met behulp van 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 tot breed

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

Op meerdere kolommen (vanaf 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

Breed tot 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

Gaan van breed naar lang formaat met behulp van smelt

Smelten: de basis

Smelten wordt gebruikt om gegevens te transformeren van breed naar lang formaat.

Beginnend met een brede dataset:

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

We kunnen onze data smelten met behulp van de melt functie in data.table. Dit retourneert een andere datatabel in lang formaat:

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 kolommen die niet zijn ingesteld in de parameter id.vars worden verondersteld variabelen te zijn. Als alternatief kunnen we deze expliciet instellen met het 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 dit geval worden kolommen die niet zijn ingesteld in measure.vars verondersteld ID's te zijn.

Als we beide expliciet instellen, worden alleen de geselecteerde kolommen geretourneerd:

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

Naamgeving variabelen en waarden in het resultaat

We kunnen de kolomnamen van de geretourneerde tabel manipuleren met behulp van variable.name en 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

Typen instellen voor meetvariabelen in het resultaat

Standaard wordt het smelten van een data.table converteert alle measure.vars factoren:

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

Gebruik in plaats daarvan het argument variable.factor om als teken in te stellen:

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

Waarden nemen over het algemeen van het gegevenstype van de oorspronkelijke kolom over:

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

Als er een conflict is, worden gegevenstypen gedwongen. Bijvoorbeeld:

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

Tijdens het smelten worden alle factorvariabelen tot het karaktertype gedwongen:

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

Om dit te voorkomen en het oorspronkelijke typen te behouden, gebruikt u het argument value.factor :

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

Omgaan met ontbrekende waarden

Standaard worden NA waarden behouden in de gesmolten gegevens

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

Als deze uit uw gegevens moeten worden verwijderd, stelt u 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

Met dcast van lang naar breed formaat gaan

Casting: The Basics

Casting wordt gebruikt om gegevens te transformeren van lang naar breed formaat.

Beginnend met een lange gegevensset:

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)

We kunnen onze gegevens casten met behulp van de dcast functie in data.table. Dit retourneert een andere datatabel in groot formaat:

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"

Een waarde uitbrengen

Een argument value.var is nodig voor een juiste cast - indien niet opgegeven, maakt dcast een veronderstelling op basis van uw gegevens.

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

Er kunnen meerdere value.var worden opgegeven in een lijst

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

Formule

Casten wordt bestuurd met behulp van het formule-argument in dcast . Dit is in de vorm 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

Zowel rijen als kolommen kunnen worden uitgebreid met verdere variabelen met +

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

Casten kan vaak cellen maken waar geen observatie in de gegevens bestaat. Standaard wordt dit aangegeven door NA , zoals hierboven. We kunnen dit overschrijven met het fill= argument.

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

U kunt ook twee speciale variabelen gebruiken in het formuleobject

  • . vertegenwoordigt geen andere variabelen
  • ... vertegenwoordigt alle andere variabelen
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

Onze waarde samenvoegen. Var

We kunnen ook waarden in één stap casten en aggregeren. In dit geval hebben we drie observaties op elk van de kruispunten van Leeftijd en ID. Om in te stellen welke aggregatie we willen gebruiken we het 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

We kunnen ook een lijst doorgeven aan fun.aggregate om meerdere functies te gebruiken

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

Als we meer dan één functie en meer dan één waarde doorgeven, kunnen we alle combinaties berekenen door een vector van waarde.vars door te geven

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

waarbij elk paar wordt berekend in de volgorde value1_formula1, value1_formula2, ... , valueN_formula(N-1), valueN_formulaN .

Als alternatief kunnen we onze waarden en functies één op één evalueren door 'value.var' als lijst door te geven:

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

Kolommen een naam geven in het resultaat

Standaard worden kolomnaamonderdelen gescheiden door een onderstrepingsteken _ . Dit kan handmatig worden opgeheven met het argument sep= :

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

Dit fun.aggregate elke fun.aggregate of value.var we gebruiken:

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

Meerdere tabellen stapelen met behulp van rbindlist

Een gemeenschappelijk refrein in R gaat als volgt:

Je moet geen stel gerelateerde tabellen hebben met namen als DT1 , DT2 , ..., DT11 . Iteratief lezen en toewijzen aan objecten op naam is rommelig. De oplossing is een lijst met gegevenstabellen!

Zo'n lijst ziet eruit

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

Een ander perspectief is dat u deze tabellen als één tabel moet opslaan door ze te stapelen. Dit is eenvoudig te doen met behulp van 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

Dit formaat is veel logischer met de syntaxis van data.table, waar "per groep" -bewerkingen gebruikelijk en eenvoudig zijn.

Voor een diepere blik is het antwoord van Gregor misschien een goede plek om te beginnen. Kijk natuurlijk ook op ?rbindlist . Er is een apart voorbeeld voor lezen in een aantal tabellen van CSV en deze vervolgens stapelen .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow