R Language
tabla de datos
Buscar..
Introducción
Data.table es un paquete que amplía la funcionalidad de los marcos de datos desde la base R, particularmente mejorando su rendimiento y sintaxis. Consulte el área de documentos del paquete en Introducción a data.table para obtener más información.
Sintaxis
-
DT[i, j, by]
# DT [donde, seleccione | actualizar | hacer, por] -
DT[...][...]
# encadenamiento -
################# Shortcuts, special functions and special symbols inside DT[...]
- . ()
# en varios argumentos, reemplaza lista () - J ()
# en i, reemplaza lista () - : =
# en j, una función utilizada para agregar o modificar columnas - .NORTE
# en i, el número total de filas
# en j, el número de filas en un grupo - .YO
# en j, el vector de los números de fila en la tabla (filtrado por i) - .DAKOTA DEL SUR
# en j, el subconjunto actual de los datos
# seleccionado por el argumento .SDcols - .GRP
# en j, el índice actual del subconjunto de los datos - .POR
# en j, la lista de por valores para el subconjunto actual de datos - V1, V2, ...
# nombres predeterminados para columnas sin nombre creadas en j -
################# Joins inside DT[...]
- DT1 [DT2, on, j]
# unir dos mesas - yo.*
# prefijo especial en las columnas de DT2 después de la unión - por = .EACHI
# opción especial disponible solo con una combinación - DT1 [! DT2, on, j]
# anti-join dos mesas - DT1 [DT2, on, roll, j]
# unir dos tablas, rodando en la última columna en on = -
################# Reshaping, stacking and splitting
- derretir (DT, id.vars, measure.vars)
# transformar a formato largo
# para columnas múltiples, use measure.vars = patterns (...) - dcast (DT, formula)
# transformar a formato ancho - rbind (DT1, DT2, ...)
# pila enumeró data.tables - rbindlist (DT_list, idcol)
# apilar una lista de data.tables - dividir (DT, por)
# divide una tabla de datos en una lista -
################# Some other functions specialized for data.tables
- foverlaps
# superposición une - unir
# Otra forma de unir dos mesas. - conjunto
# Otra forma de agregar o modificar columnas. - fintersect, fsetdiff, funion, fsetequal, unique, duplicated, anyDuplicated
# operaciones de set-theory con filas como elementos - únicoN
# el número de filas distintas - rowidv (DT, cols)
# ID de fila (1 a .N) dentro de cada grupo determinado por cols - rleidv (DT, cols)
# ID de grupo (1 a .GRP) dentro de cada grupo determinado por ejecuciones de cols - shift (DT, n, type = c ("lag", "lead"))
# aplicar un operador de turno a cada columna - setorder, setcolorder, setnames, setkey, setindex, setattr
# modificar atributos y ordenar por referencia
Observaciones
Instalación y soporte
Para instalar el paquete data.table:
# install from CRAN
install.packages("data.table")
# or install development version
install.packages("data.table", type = "source", repos = "http://Rdatatable.github.io/data.table")
# and to revert from devel to CRAN, the current version must first be removed
remove.packages("data.table")
install.packages("data.table")
El sitio oficial del paquete tiene páginas wiki que proporcionan ayuda para comenzar, y listas de presentaciones y artículos de toda la web. Antes de hacer una pregunta, aquí en StackOverflow o en cualquier otro lugar, lea la página de soporte .
Cargando el paquete
Muchas de las funciones en los ejemplos anteriores existen en el espacio de nombres data.table. Para usarlos, primero deberá agregar una línea como library(data.table)
o usar su ruta completa, como data.table::fread
lugar de simplemente fread
. Para obtener ayuda sobre funciones individuales, la sintaxis es help("fread")
o ?fread
. Nuevamente, si el paquete no está cargado, use el nombre completo como ?data.table::fread
.
Creando una tabla de datos
Un data.table es una versión mejorada de la clase data.frame desde la base R. Como tal, su atributo class()
es el vector "data.table" "data.frame"
y las funciones que funcionan en un data.frame también Trabajar con una tabla de datos. Hay muchas formas de crear, cargar o forzar una tabla de datos.
Construir
No olvides instalar y activar el paquete data.table
.
library(data.table)
Hay un constructor del mismo nombre:
DT <- data.table(
x = letters[1:5],
y = 1:5,
z = (1:5) > 3
)
# x y z
# 1: a 1 FALSE
# 2: b 2 FALSE
# 3: c 3 FALSE
# 4: d 4 TRUE
# 5: e 5 TRUE
A diferencia de data.frame
, data.table
no data.table
cadenas a factores:
sapply(DT, class)
# x y z
# "character" "integer" "logical"
Leer en
Podemos leer desde un archivo de texto:
dt <- fread("my_file.csv")
A diferencia de read.csv
, fread
leerá cadenas como cadenas, no como factores.
Modificar un data.frame
Para una mayor eficiencia, data.table ofrece una forma de alterar un data.frame o lista para hacer una data.table en el lugar (sin hacer una copia o cambiar su ubicación de memoria):
# example data.frame
DF <- data.frame(x = letters[1:5], y = 1:5, z = (1:5) > 3)
# modification
setDT(DF)
Tenga en cuenta que no <-
asignamos el resultado, ya que el objeto DF
se ha modificado in situ. Los atributos de clase del data.frame se mantendrán:
sapply(DF, class)
# x y z
# "factor" "integer" "logical"
Coercer objeto a data.table
Si tiene una list
, data.frame
o data.table
, debe usar la función setDT
para convertir a data.table
porque realiza la conversión por referencia en lugar de hacer una copia (que as.data.table
hace). Esto es importante si está trabajando con grandes conjuntos de datos.
Si tiene otro objeto R (como una matriz), debe usar as.data.table
para as.data.table
a una data.table
.
mat <- matrix(0, ncol = 10, nrow = 10)
DT <- as.data.table(mat)
# or
DT <- data.table(mat)
Añadiendo y modificando columnas.
DT[where, select|update|do, by]
sintaxis de DT[where, select|update|do, by]
se utiliza para trabajar con columnas de una tabla de datos.
- La parte "donde" es el argumento
i
- La parte "seleccionar | actualizar | hacer" es el argumento
j
Estos dos argumentos generalmente se pasan por posición en lugar de por nombre.
Nuestro ejemplo de datos a continuación es
mtcars = data.table(mtcars, keep.rownames = TRUE)
Editando columnas enteras
Use el operador :=
dentro de j
para asignar nuevas columnas:
mtcars[, mpg_sq := mpg^2]
Elimine las columnas estableciendo NULL
:
mtcars[, mpg_sq := NULL]
Agregue varias columnas usando el formato multivariado del operador :=
mtcars[, `:=`(mpg_sq = mpg^2, wt_sqrt = sqrt(wt))]
# or
mtcars[, c("mpg_sq", "wt_sqrt") := .(mpg^2, sqrt(wt))]
Si las columnas son dependientes y deben definirse en secuencia, una forma es:
mtcars[, c("mpg_sq", "mpg2_hp") := .(temp1 <- mpg^2, temp1/hp)]
La sintaxis .()
Se usa cuando el lado derecho de LHS := RHS
es una lista de columnas.
Para nombres de columna determinados dinámicamente, use paréntesis:
vn = "mpg_sq"
mtcars[, (vn) := mpg^2]
Las columnas también se pueden modificar con el set
, aunque esto rara vez es necesario:
set(mtcars, j = "hp_over_wt", v = mtcars$hp/mtcars$wt)
Edición de subconjuntos de columnas
Utilice el argumento i
para subcontratar a las filas "donde" se deben realizar las ediciones:
mtcars[1:3, newvar := "Hello"]
# or
set(mtcars, j = "newvar", i = 1:3, v = "Hello")
Al igual que en un data.frame, podemos subcontratar utilizando números de fila o pruebas lógicas. También es posible utilizar una "unión" en i
, pero en otro ejemplo se trata una tarea más complicada.
Edición de atributos de columna
Las funciones que editan atributos, como los levels<-
o names<-
, reemplazan un objeto con una copia modificada. Incluso si solo se utiliza en una columna en una tabla de datos, todo el objeto se copia y se reemplaza.
Para modificar un objeto sin copias, use setnames
para cambiar los nombres de columna de data.table o data.frame y setattr
para cambiar un atributo para cualquier objeto.
# Print a message to the console whenever the data.table is copied
tracemem(mtcars)
mtcars[, cyl2 := factor(cyl)]
# Neither of these statements copy the data.table
setnames(mtcars, old = "cyl2", new = "cyl_fac")
setattr(mtcars$cyl_fac, "levels", c("four", "six", "eight"))
# Each of these statements copies the data.table
names(mtcars)[names(mtcars) == "cyl_fac"] <- "cf"
levels(mtcars$cf) <- c("IV", "VI", "VIII")
Tenga en cuenta que estos cambios se realizan por referencia, por lo que son globales . Cambiarlos dentro de un entorno afecta al objeto en todos los entornos.
# This function also changes the levels in the global environment
edit_levels <- function(x) setattr(x, "levels", c("low", "med", "high"))
edit_levels(mtcars$cyl_factor)
Símbolos especiales en tabla de datos.
.DAKOTA DEL SUR
.SD
refiere al subconjunto de la data.table
de data.table
para cada grupo, excluyendo todas las columnas utilizadas by
.
.SD
junto con lapply
se puede usar para aplicar cualquier función a varias columnas por grupo en una data.table
Continuaremos usando el mismo conjunto de datos mtcars
, mtcars
:
mtcars = data.table(mtcars) # Let's not include rownames to keep things simpler
Media de todas las columnas en el conjunto de datos por número de cilindros , cyl
:
mtcars[ , lapply(.SD, mean), by = cyl]
# cyl mpg disp hp drat wt qsec vs am gear carb
#1: 6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 3.428571
#2: 4 26.66364 105.1364 82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 1.545455
#3: 8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 3.500000
Aparte de cyl
, hay otras columnas categóricas en el conjunto de datos como vs
, am
, gear
y carb
. Realmente no tiene sentido tomar la mean
de estas columnas. Así que vamos a excluir estas columnas. Aquí es donde .SDcols
entra en escena.
.SDcols
.SDcols
especifica las columnas de la data.table
que se incluyen en .SD
.
La media de todas las columnas (columnas continuas) en el conjunto de datos por número de engranajes gear
, y el número de cilindros, cyl
, dispuestos por gear
y cyl
:
# All the continuous variables in the dataset
cols_chosen <- c("mpg", "disp", "hp", "drat", "wt", "qsec")
mtcars[order(gear, cyl), lapply(.SD, mean), by = .(gear, cyl), .SDcols = cols_chosen]
# gear cyl mpg disp hp drat wt qsec
#1: 3 4 21.500 120.1000 97.0000 3.700000 2.465000 20.0100
#2: 3 6 19.750 241.5000 107.5000 2.920000 3.337500 19.8300
#3: 3 8 15.050 357.6167 194.1667 3.120833 4.104083 17.1425
#4: 4 4 26.925 102.6250 76.0000 4.110000 2.378125 19.6125
#5: 4 6 19.750 163.8000 116.5000 3.910000 3.093750 17.6700
#6: 5 4 28.200 107.7000 102.0000 4.100000 1.826500 16.8000
#7: 5 6 19.700 145.0000 175.0000 3.620000 2.770000 15.5000
#8: 5 8 15.400 326.0000 299.5000 3.880000 3.370000 14.5500
Tal vez no queremos calcular la mean
por grupos. Para calcular la media de todos los autos en el conjunto de datos, no especificamos la variable by
.
mtcars[ , lapply(.SD, mean), .SDcols = cols_chosen]
# mpg disp hp drat wt qsec
#1: 20.09062 230.7219 146.6875 3.596563 3.21725 17.84875
Nota:
- No es necesario definir
cols_chosen
antemano..SDcols
puede tomar directamente nombres de columna -
.SDcols
también puede tomar directamente un vector de números de columna. En el ejemplo anterior, esto seríamtcars[ , lapply(.SD, mean), .SDcols = c(1,3:7)]
.NORTE
.N
es una abreviatura de la cantidad de filas en un grupo.
iris[, .(count=.N), by=Species]
# Species count
#1: setosa 50
#2: versicolor 50
#3: virginica 50
Escribir código compatible tanto con data.frame como con data.table
Diferencias en la sintaxis del subconjunto.
A data.table
es una de varias estructuras de datos bidimensionales disponibles en R, además de data.frame
, matrix
y (2D) array
. Todas estas clases utilizan una sintaxis muy similar pero no idéntica para la subconjunto, el esquema A[rows, cols]
.
Considere los siguientes datos almacenados en una matrix
, un data.frame
y un data.table
:
ma <- matrix(rnorm(12), nrow=4, dimnames=list(letters[1:4], c('X', 'Y', 'Z')))
df <- as.data.frame(ma)
dt <- as.data.table(ma)
ma[2:3] #---> returns the 2nd and 3rd items, as if 'ma' were a vector (because it is!)
df[2:3] #---> returns the 2nd and 3rd columns
dt[2:3] #---> returns the 2nd and 3rd rows!
Si desea estar seguro de lo que se devolverá, es mejor ser explícito .
Para obtener filas específicas, solo agregue una coma después del rango:
ma[2:3, ] # \
df[2:3, ] # }---> returns the 2nd and 3rd rows
dt[2:3, ] # /
Pero, si desea subcontratar columnas , algunos casos se interpretan de manera diferente. Los tres pueden ser subconjuntos de la misma manera con índices enteros o de caracteres no almacenados en una variable.
ma[, 2:3] # \
df[, 2:3] # \
dt[, 2:3] # }---> returns the 2nd and 3rd columns
ma[, c("Y", "Z")] # /
df[, c("Y", "Z")] # /
dt[, c("Y", "Z")] # /
Sin embargo, difieren para nombres de variables sin comillas
mycols <- 2:3
ma[, mycols] # \
df[, mycols] # }---> returns the 2nd and 3rd columns
dt[, mycols, with = FALSE] # /
dt[, mycols] # ---> Raises an error
En el último caso, mycols
se evalúa como el nombre de una columna. Debido a que dt
no puede encontrar una columna llamada mycols
, se mycols
un error.
Nota: Para las versiones de la data.table
paquete priorto 1.9.8, este comportamiento fue un poco diferente. Cualquier cosa en el índice de la columna habría sido evaluada utilizando dt
como un entorno. Entonces, tanto dt[, 2:3]
como dt[, mycols]
devolverían el vector 2:3
. No se mycols
ningún error para el segundo caso, porque la variable mycols
existe en el entorno principal.
Estrategias para mantener la compatibilidad con data.frame y data.table.
Hay muchas razones para escribir código que está garantizado para trabajar con data.frame
y data.table
. Tal vez se vea obligado a usar data.frame
, o tal vez necesite compartir un código que no sabe cómo se usará. Por lo tanto, hay algunas estrategias principales para lograr esto, en orden de conveniencia:
- Utilice la sintaxis que se comporta de la misma manera para ambas clases.
- Utilice una función común que haga lo mismo que la sintaxis más corta.
- Forzar
data.table
para que se comporte comodata.frame
(ej .: llamar al método específicoprint.data.frame
). - Trátelos como
list
, que son en última instancia. - Convierta la tabla en un
data.frame
antes de hacer cualquier cosa (mala idea si es una tabla enorme). - Convierta la tabla a
data.table
, si las dependencias no son una preocupación.
Subconjunto de filas. Es simple, solo use el selector [, ]
, con la coma:
A[1:10, ]
A[A$var > 17, ] # A[var > 17, ] just works for data.table
Subconjuntar columnas. Si desea una sola columna, use el selector $
o [[ ]]
:
A$var
colname <- 'var'
A[[colname]]
A[[1]]
Si desea una forma uniforme de capturar más de una columna, es necesario apelar un poco:
B <- `[.data.frame`(A, 2:4)
# We can give it a better name
select <- `[.data.frame`
B <- select(A, 2:4)
C <- select(A, c('foo', 'bar'))
Subconjunto de filas 'indexadas'. Mientras que data.frame
tiene row.names
, data.table
tiene su característica key
única. Lo mejor es evitar row.names
completo row.names
y aprovechar las optimizaciones existentes en el caso de data.table
cuando sea posible.
B <- A[A$var != 0, ]
# or...
B <- with(A, A[var != 0, ]) # data.table will silently index A by var before subsetting
stuff <- c('a', 'c', 'f')
C <- A[match(stuff, A$name), ] # really worse than: setkey(A); A[stuff, ]
Obtener una tabla de 1 columna, obtener una fila como un vector. Estos son fáciles con lo que hemos visto hasta ahora:
B <- select(A, 2) #---> a table with just the second column
C <- unlist(A[1, ]) #---> the first row as a vector (coerced if necessary)
Configuración de teclas en data.table
Sí, necesitas SETKEY pre 1.9.6
En el pasado (anterior a 1.9.6), su data.table
se aceleró al establecer columnas como claves de la tabla, particularmente para tablas grandes. [Vea la introducción en la página 5 de la versión de septiembre de 2015, donde la velocidad de búsqueda fue 544 veces mejor.] Puede encontrar códigos más antiguos que utilizan estas teclas de configuración con la tecla 'setkey' o una columna 'key =' al configurar la tabla.
library(data.table)
DT <- data.table(
x = letters[1:5],
y = 5:1,
z = (1:5) > 3
)
#> DT
# x y z
#1: a 5 FALSE
#2: b 4 FALSE
#3: c 3 FALSE
#4: d 2 TRUE
#5: e 1 TRUE
Establece tu clave con el comando setkey
. Puedes tener una clave con múltiples columnas.
setkey(DT, y)
Verifique la llave de su mesa en tablas ()
tables()
> tables()
NAME NROW NCOL MB COLS KEY
[1,] DT 5 3 1 x,y,z y
Total: 1MB
Tenga en cuenta que esto reordena sus datos.
#> DT
# x y z
#1: e 1 TRUE
#2: d 2 TRUE
#3: c 3 FALSE
#4: b 4 FALSE
#5: a 5 FALSE
Ahora es innecesario
Antes de v1.9.6 tenía que haber establecido una clave para ciertas operaciones, especialmente para unir tablas. Los desarrolladores de data.table han acelerado e introducido una función "on="
que puede reemplazar la dependencia de las claves. Vea SO aquí para una discusión detallada.
En enero de 2017, los desarrolladores escribieron una viñeta alrededor de los índices secundarios que explica la sintaxis "on" y permite que se identifiquen otras columnas para una indexación rápida.
¿Creando índices secundarios?
De una manera similar a la clave, puede establecer setindex(DT, key.col)
o setindexv(DT, "key.col.string")
, donde DT es su tabla de datos. Eliminar todos los índices con setindex(DT, NULL)
.
Consulte sus índices secundarios con indices(DT)
.
¿Por qué índices secundarios?
Esto no ordena la tabla (a diferencia de la clave), pero permite una indexación rápida utilizando la sintaxis "on". Tenga en cuenta que solo puede haber una clave, pero puede usar múltiples índices secundarios, lo que ahorra tener que cambiar la configuración de la tabla. Esto acelerará su subconjunto cuando cambie las columnas en las que desea subconjuntar.
Recuerde, en el ejemplo anterior y fue la clave para la tabla DT:
DT
# x y z
# 1: e 1 TRUE
# 2: d 2 TRUE
# 3: c 3 FALSE
# 4: b 4 FALSE
# 5: a 5 FALSE
# Let us set x as index
setindex(DT, x)
# Use indices to see what has been set
indices(DT)
# [1] "x"
# fast subset using index and not keyed column
DT["c", on ="x"]
#x y z
#1: c 3 FALSE
# old way would have been rekeying DT from y to x, doing subset and
# perhaps keying back to y (now we save two sorts)
# This is a toy example above but would have been more valuable with big data sets