data.tableAndreu 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]i ~ wherej ~ selectby ~ group byPer 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
data.tablePodem 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 clausPer 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
jL'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
byPodem 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
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
:=nomatch.SDwith = FALSEPodeu 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
example(data.table)A més de ser utilíssim, és eficient!
Moltes gràcies!