Introducció al paquet data.table

Andreu Vall - RUG Barcelona

20 de juny de 2013

"Enhanced data.frame. Fast indexing, fast ordered joins, fast assignment, fast grouping and list columns in a short and flexible syntax. i and j may be expressions of column names directly, for faster development. Example: X[Y] is a fast join for large data."

Referències d'aquesta presentació:

dt[i, j, by]

Per exemple,

subset(climate, select = c(year, population, continent))
##       year population continent
##    1: 1990      62147 S.AMERICA
##    2: 1991      64642 S.AMERICA
##    3: 1992      68286 S.AMERICA
##    4: 1993      72573 S.AMERICA
##    5: 1994      76762 S.AMERICA
##   ---                          
## 4558: 2006   12529655    AFRICA
## 4559: 2007   12481245    AFRICA
## 4560: 2008   12451543    AFRICA
## 4561: 2009   12473992    AFRICA
## 4562: 2010   12571454    AFRICA
climate[year == 2010, sum(population), by = continent]
##    continent        V1
## 1: S.AMERICA 3.925e+08
## 2:    EUROPE 6.143e+08
## 3:      ASIA 4.071e+09
## 4:    AFRICA 1.021e+09
## 5:   OCEANIA 3.777e+07
## 6: N.AMERICA 5.398e+08
## 7:        NA 1.418e+08

Crear una data.table

Podem crear un data.table exactament com ho fem amb un data.frame.

df <- data.frame(x = c("b", "b", "b", "a", "a"), y = c(1, 2, 2, 2, 1), v = rnorm(5))
df
##   x y       v
## 1 b 1 -0.6265
## 2 b 2  0.1836
## 3 b 2 -0.8356
## 4 a 2  1.5953
## 5 a 1  0.3295
dt <- data.table(x = c("b", "b", "b", "a", "a"), y = c(1, 2, 2, 2, 1), v = rnorm(5))
dt
##    x y       v
## 1: b 1 -0.8205
## 2: b 2  0.4874
## 3: b 2  0.7383
## 4: a 2  0.5758
## 5: a 1 -0.3054

O bé podem convertir de data.frame a data.table.

dt_from_df <- as.data.table(df)
dt_from_df
##    x y       v
## 1: b 1 -0.6265
## 2: b 2  0.1836
## 3: b 2 -0.8356
## 4: a 2  1.5953
## 5: a 1  0.3295

Fixeu-vos que...

class(dt)
## [1] "data.table" "data.frame"

i i les claus

Per consultar una taula és possible imitar la sintaxi de data.frame...

df[df$x == "a", ]
##   x y      v
## 4 a 2 1.5953
## 5 a 1 0.3295
dt[x == "a"]
##    x y       v
## 1: a 2  0.5758
## 2: a 1 -0.3054
df[2, ]
##   x y      v
## 2 b 2 0.1836
dt[2, ]
##    x y      v
## 1: b 2 0.4874

però no del tot (vegeu FAQ 1.1).

dt[2, 3]
## [1] 3

Tot i així, la manera eficient de fer la consulta és assignar una clau a la taula. Fixeu-vos en l'ordenació de la taula.

setkey(dt, x)
dt
##    x y       v
## 1: a 2  0.5758
## 2: a 1 -0.3054
## 3: b 1 -0.8205
## 4: b 2  0.4874
## 5: b 2  0.7383
dt["b"]
##    x y       v
## 1: b 1 -0.8205
## 2: b 2  0.4874
## 3: b 2  0.7383

La clau pot constar de més d'una columna. De nou, fixeu-vos en l'ordenació de la taula. En aquest cas ens caldrà fer servir J() (és un àlies de data.table i una abreviació de join).

setkey(dt, x, y)
dt
##    x y       v
## 1: a 1 -0.3054
## 2: a 2  0.5758
## 3: b 1 -0.8205
## 4: b 2  0.4874
## 5: b 2  0.7383
dt[J("b", 2)]
##    x y      v
## 1: b 2 0.4874
## 2: b 2 0.7383
dt[J("a", 2)]
##    x y      v
## 1: a 2 0.5758

j

L'argument j ens permet seleccionar quines columnes volem consultar.

dt
##    x y       v
## 1: a 1 -0.3054
## 2: a 2  0.5758
## 3: b 1 -0.8205
## 4: b 2  0.4874
## 5: b 2  0.7383
dt[, x]
## [1] "a" "a" "b" "b" "b"
dt[, y]
## [1] 1 2 1 2 2
dt[, v]
## [1] -0.3054  0.5758 -0.8205  0.4874  0.7383

De fet, és més general: ens permet consultar una o més expressions formades amb columnes.

dt[, sum(v)]
## [1] 0.6757
dt[, list(x, y)]
##    x y
## 1: a 1
## 2: a 2
## 3: b 1
## 4: b 2
## 5: b 2
dt[, list(suma = y + v)]
##      suma
## 1: 0.6946
## 2: 2.5758
## 3: 0.1795
## 4: 2.4874
## 5: 2.7383

by

Podem combinar una expressió j amb by de manera que l'expressió s'apliqui a cada grup definit pel by.

dt[, sum(v), by = x]
##    x     V1
## 1: a 0.2704
## 2: b 0.4053
dt[, max(v), by = x]
##    x     V1
## 1: a 0.5758
## 2: b 0.7383
dt[, list(max_v = max(v)), by = x]
##    x  max_v
## 1: a 0.5758
## 2: b 0.7383

El by pot estar definit per més d'una columna ...

dt[, sum(v), by = "x,y"]
##    x y      V1
## 1: a 1 -0.3054
## 2: a 2  0.5758
## 3: b 1 -0.8205
## 4: b 2  1.2258
dt[, sum(v), by = list(x, y)]
##    x y      V1
## 1: a 1 -0.3054
## 2: a 2  0.5758
## 3: b 1 -0.8205
## 4: b 2  1.2258

o per expressions.

dt[, list(max_y = max(y)), by = list(round_v = round(v))]
##    round_v max_y
## 1:       0     2
## 2:       1     2
## 3:      -1     1

Finalment podem combinar i, j i by.

dt
##    x y       v
## 1: a 1 -0.3054
## 2: a 2  0.5758
## 3: b 1 -0.8205
## 4: b 2  0.4874
## 5: b 2  0.7383
key(dt)
## [1] "x" "y"
dt["b", list(prod_v = prod(v)), by = y]
##    y  prod_v
## 1: 1 -0.8205
## 2: 2  0.3599

Join

Quan hem consultat la taula amb dt["b",], o amb dt[J("b",2)], ja hem comentat que estàvem fent un join. Vegem-ho amb més exemples.

dt_info <- data.table(x = c("a", "b"), info = c("info_a", "info_b"))
dt_info
##    x   info
## 1: a info_a
## 2: b info_b

Per unir dues taules és important vigilar les claus.

setkey(dt_info, x)
setkey(dt, x)
dt[dt_info]
##    x y       v   info
## 1: a 1 -0.3054 info_a
## 2: a 2  0.5758 info_a
## 3: b 1 -0.8205 info_b
## 4: b 2  0.4874 info_b
## 5: b 2  0.7383 info_b

En general, X[Y] és diferent de Y[X] i de merge (vegeu FAQ 1.12).

dt_info[dt]
##    x   info y       v
## 1: a info_a 1 -0.3054
## 2: a info_a 2  0.5758
## 3: b info_b 1 -0.8205
## 4: b info_b 2  0.4874
## 5: b info_b 2  0.7383
merge(dt_info, dt)
##    x   info y       v
## 1: a info_a 1 -0.3054
## 2: a info_a 2  0.5758
## 3: b info_b 1 -0.8205
## 4: b info_b 2  0.4874
## 5: b info_b 2  0.7383

En aquest cas coincideixen, tot i que no té perquè ser així.

identical(dt_info[dt], merge(dt_info, dt))
## [1] TRUE

Per exemple,

dt_info_buits <- data.table(x = "a", info = "info_a")
setkey(dt_info_buits, x)
setkey(dt, x)
dt[dt_info_buits]
##    x y       v   info
## 1: a 1 -0.3054 info_a
## 2: a 2  0.5758 info_a
dt_info_buits[dt]
##    x   info y       v
## 1: a info_a 1 -0.3054
## 2: a info_a 2  0.5758
## 3: b     NA 1 -0.8205
## 4: b     NA 2  0.4874
## 5: b     NA 2  0.7383
merge(dt, dt_info_buits)
##    x y       v   info
## 1: a 1 -0.3054 info_a
## 2: a 2  0.5758 info_a

Més coses que heu de buscar

Com aprendre'n

Podeu començar per la introducció

Quan l'hàgiu llegit i comenceu a experimentar, tingueu a mà

Navegueu pels exemples: n'hi ha de bàsics i de sofisticadíssims

A més de ser utilíssim, és eficient!

Moltes gràcies!