Capitulo 7 data.table
El package data.table es un paquete que lleva la eficiencia al siguiente nivel. Como dije, la sintaxis es algo menos intuitiva que el lenguaje tidyverse pero todo sea por la eficiencia :).
Los Data Table pueden ser utilizados como data.rame. Si se hace un class(...) de un data.table se imprime una lista con dos valores: “data.table” “data.frame”, identificando que los objetos data.able también pueden ser considerados como data.frame y las librerías que solo usan data.frame no tendrían problemas al usar data.table.
7.1 Importar y exportar datos
El package data.table tiene sus propias funciones para importar y exportar datos. Las funciones son fread() y fwrite(). Estas funciones sirven para cargar archivos tabulares, o de texto, separados por cierto separados. Aquí tenemos los argumentos más importantes de estas funciones:
x: el objeto que queremos exportar. En caso de importar, esto no hace falta.file: el lugar donde queremos guardar el archivo y su extensión.sep: el delimitador entre columnas. En un archivo csv por lo general es “,”dec: el separador decimal.dateTimeAs: formato en el que guardar objetos de fecha. Por defecto es “ISO”.
Vamos a probar a cargar “Historicos”
data.link = "C:/Users/ip30/Dropbox/Terreno/cursos/Formadores IT/Curso intro R/Curso R base/datos/"
HS <- fread(paste0(data.link,"Historicos_siniestros.txt"),sep=";",dec=",")
str(HS)
## Classes 'data.table' and 'data.frame':   29096 obs. of  15 variables:
##  $ CO_SINIESTRO               : int  2361644 2361644 2361644 2361644 2361644 2361644 2361644 2361644 2361644 2361644 ...
##  $ IN_ORDEN                   : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ FX_OPERACION               : chr  "04Jul2018" "01Aug2018" "02Aug2018" "10Aug2018" ...
##  $ FX_DECLARACION_SINIESTRO   : chr  "04Jul2018" "01Aug2018" "01Aug2018" "01Aug2018" ...
##  $ FX_ENTRADA_SINIESTRO       : chr  "04Jul2018" "01Aug2018" "01Aug2018" "01Aug2018" ...
##  $ FX_ADMISION_SINIESTRO      : chr  "" "" "02Aug2018" "02Aug2018" ...
##  $ CO_SITUACION_SINIESTRO     : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ CO_MOTIVO_RECHAZO_SINIESTRO: int  0 0 0 0 0 0 0 0 0 0 ...
##  $ CO_TIPO_ESTADO_SINIESTRO   : int  9 4 5 5 5 1 1 3 3 3 ...
##  $ IM_CREDITO_TOTAL           : num  7000 7000 4200 4200 4200 4200 4200 4200 4200 4200 ...
##  $ IM_CREDITO_PENDIENTE       : num  7000 7000 4200 4200 4200 4200 4200 4200 4200 4200 ...
##  $ IM_SUMA_ASEGURADA          : num  0 0 3780 3780 3780 3780 3780 3780 3780 3780 ...
##  $ IM_SUMA_GARANTIZADA        : num  0 0 3213 3213 3213 ...
##  $ IM_SINIESTRO_CREDITO       : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ IM_SINIESTRO_CREDITO_ACU   : num  0 0 0 0 0 0 0 0 0 0 ...
##  - attr(*, ".internal.selfref")=<externalptr>Como vemos, el formato data.table es algo diferente a los tibble de tidyverse, pero no os preocupeis, es muy parecido :)
Cargar fechas es una de las limitaciones actuales de read.table, pero seguramente pronto renovarán la función para ello. Podemos usar la función que vimos anydate() o anytime() para poner bien las variables que nos interesan.
7.2 Sintaxis base
Esta es la base para manejarnos con una data.table: DT[ i , j , by ]. Tiene tres partes que hemos llamado i, j y by:
i: corresponde a las líneas con las que queremos trabajar.j: corresponde a las columnas y la usaremos para hacer cálculos y resúmenes, seleccionar variables y crear nuevas variables.by: corresponde a las agrupaciones que queremos hacer.
7.2.1 La parte i
La parte i se usa para filtrar las líneas con las que queremos trabajar. Por ejemplo:
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1:          4.9         3.0          1.4         0.2  setosa
## 2:          4.7         3.2          1.3         0.2  setosa
## 3:          4.6         3.1          1.5         0.2  setosa
## 4:          5.0         3.6          1.4         0.2  setosa
## 5:          5.4         3.9          1.7         0.4  setosa
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1:          4.9         3.0          1.4         0.2  setosa
## 2:          4.7         3.2          1.3         0.2  setosa
## 3:          4.6         3.1          1.5         0.2  setosa
## 4:          5.0         3.6          1.4         0.2  setosa
## 5:          5.4         3.9          1.7         0.4  setosa
O también podemos usar nombres de columnas y condiciones para hacer esto:
IRIS[Species %in% c("setosa","virginica")][1:4]
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1:          5.1         3.5          1.4         0.2  setosa
## 2:          4.9         3.0          1.4         0.2  setosa
## 3:          4.7         3.2          1.3         0.2  setosa
## 4:          4.6         3.1          1.5         0.2  setosaY podemos poner varias condiciones:
IRIS[Species == "setosa" | Species=="virginica" ][1:5]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1:          5.1         3.5          1.4         0.2  setosa
## 2:          4.9         3.0          1.4         0.2  setosa
## 3:          4.7         3.2          1.3         0.2  setosa
## 4:          4.6         3.1          1.5         0.2  setosa
## 5:          5.0         3.6          1.4         0.2  setosa
IRIS[Species %in% c("setosa","virginica") & Petal.Width < 1][1:3]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1:          5.1         3.5          1.4         0.2  setosa
## 2:          4.9         3.0          1.4         0.2  setosa
## 3:          4.7         3.2          1.3         0.2  setosaFijaros, que he concatenado varios [] seguidos, y le hemos dado la forma IRIS[][]. Esto es una concatenación de acciones, muy parecido a lo que haciamos con %>% en tidyverse.
7.2.2 La parte j
La parte j se usa para seleccionar columnas, crear nuevas variables y aplicar cosas o funciones sobre ellas ellas.
7.2.2.1 Operaciones y resumen de variales
Podemos sacar valores de interés
IRIS[1:20,mean(Petal.Length)]
## [1] 1.435
IRIS[,table(Species)]
## Species
##     setosa versicolor  virginica 
##         50         50         50En la primera línea hemos sacado la media de “Sepal.Length” para las 20 primeras observaciones. Y en la segunda línea hemos sacado cuantas observaciones tenemos para cada “Species” :)
Si queremos seleccionar varias columnas en la parte j y queremos hacer cosas con ellas, debemos usar el verbo .(). Es como si usásemos el verbo list()
Y podemos ponerle nombres para ser claros:
7.2.2.2 Seleccionar
Podemos seleccionar variables.
7.2.2.3 Crear
Mediante := también podemos crear nuevas columnas:
IRIS[, sepal_area := Sepal.Length*Sepal.Width][1:3]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species sepal_area
## 1:          5.1         3.5          1.4         0.2  setosa      17.85
## 2:          4.9         3.0          1.4         0.2  setosa      14.70
## 3:          4.7         3.2          1.3         0.2  setosa      15.04Y si queremos hacer esto con varias variables:
IRIS[, `:=`(sepal_area = Sepal.Length*Sepal.Width,
            petal_area = Petal.Length*Petal.Width)][1:3]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species sepal_area
## 1:          5.1         3.5          1.4         0.2  setosa      17.85
## 2:          4.9         3.0          1.4         0.2  setosa      14.70
## 3:          4.7         3.2          1.3         0.2  setosa      15.04
##    petal_area
## 1:       0.28
## 2:       0.28
## 3:       0.26
# o
IRIS[, c("sepal_area", "petal_area") := .(Sepal.Length*Sepal.Width, Petal.Length*Petal.Width)][1:3]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species sepal_area
## 1:          5.1         3.5          1.4         0.2  setosa      17.85
## 2:          4.9         3.0          1.4         0.2  setosa      14.70
## 3:          4.7         3.2          1.3         0.2  setosa      15.04
##    petal_area
## 1:       0.28
## 2:       0.28
## 3:       0.26y si queremos crear variables de forma secuencial:
IRIS[, c("sepal_area", "cuadrado_sepal_area") := .(a <- Sepal.Length*Sepal.Width, a^2)][1:3]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species sepal_area
## 1:          5.1         3.5          1.4         0.2  setosa      17.85
## 2:          4.9         3.0          1.4         0.2  setosa      14.70
## 3:          4.7         3.2          1.3         0.2  setosa      15.04
##    petal_area cuadrado_sepal_area
## 1:       0.28            318.6225
## 2:       0.28            216.0900
## 3:       0.26            226.20167.2.3 La parte by
Como podemos imaginar, se hacen las agrupaciones que puedan interesarnos para sacar operaciones sobre la parte j. Por ejemplo:
IRIS[,.(media_PL = mean(Petal.Length)),by=Species]
##       Species media_PL
## 1:     setosa    1.462
## 2: versicolor    4.260
## 3:  virginica    5.552
IRIS[,.(media_PL = mean(Petal.Length)), Species]
##       Species media_PL
## 1:     setosa    1.462
## 2: versicolor    4.260
## 3:  virginica    5.552Sacamos la media de “Petal.Length” por “Species”. Igual que antes, si queremos agrupar por varias variables, usaremos .():
IRIS[,col := rep(c("A","B"),length.out=nrow(IRIS))] ## hemos creado una nueva variables en IRIS
IRIS[1:7]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species sepal_area
## 1:          5.1         3.5          1.4         0.2  setosa      17.85
## 2:          4.9         3.0          1.4         0.2  setosa      14.70
## 3:          4.7         3.2          1.3         0.2  setosa      15.04
## 4:          4.6         3.1          1.5         0.2  setosa      14.26
## 5:          5.0         3.6          1.4         0.2  setosa      18.00
## 6:          5.4         3.9          1.7         0.4  setosa      21.06
## 7:          4.6         3.4          1.4         0.3  setosa      15.64
##    petal_area cuadrado_sepal_area col
## 1:       0.28            318.6225   A
## 2:       0.28            216.0900   B
## 3:       0.26            226.2016   A
## 4:       0.30            203.3476   B
## 5:       0.28            324.0000   A
## 6:       0.68            443.5236   B
## 7:       0.42            244.6096   A
IRIS[,.(media_PL = mean(Petal.Length)),by=.(Species,col)]
##       Species col media_PL
## 1:     setosa   A    1.456
## 2:     setosa   B    1.468
## 3: versicolor   A    4.308
## 4: versicolor   B    4.212
## 5:  virginica   A    5.564
## 6:  virginica   B    5.5407.2.4 Algunas otras funciones interesantes:
7.2.4.1 .N
.N en i nos da la última fila. En j el número de filas en un grupo.
7.2.4.2 .I
.I en j nos da un vector con los números de fila de los dato en la table (filtrados por i ).
(a <- IRIS[,.I[Species=="virginica"]])
##  [1] 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
## [20] 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
## [39] 139 140 141 142 143 144 145 146 147 148 149 150
IRIS[a[1:3]]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species sepal_area
## 1:          6.3         3.3          6.0         2.5 virginica      20.79
## 2:          5.8         2.7          5.1         1.9 virginica      15.66
## 3:          7.1         3.0          5.9         2.1 virginica      21.30
##    petal_area cuadrado_sepal_area col
## 1:      15.00            432.2241   A
## 2:       9.69            245.2356   B
## 3:      12.39            453.6900   A7.2.4.3 .SD
.SD en j nos trabaja sobre el subgrupo de datos seleccionados en by.
IRIS[,index := 1:nrow(IRIS)] #  crear variable index
IRIS[,.SD[1],Species] ## primera fila de cada grupoIRIS
##       Species Sepal.Length Sepal.Width Petal.Length Petal.Width sepal_area
## 1:     setosa          5.1         3.5          1.4         0.2      17.85
## 2: versicolor          7.0         3.2          4.7         1.4      22.40
## 3:  virginica          6.3         3.3          6.0         2.5      20.79
##    petal_area cuadrado_sepal_area col index
## 1:       0.28            318.6225   A     1
## 2:       6.58            501.7600   A    51
## 3:      15.00            432.2241   A   101
IRIS[,.SD[.N],Species] ## última fila de cada grupo
##      Species Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1:     setosa          5.0         3.3          1.4         0.2
## 2: versicolor          5.7         2.8          4.1         1.3
## 3:  virginica          5.9         3.0          5.1         1.8
IRIS[,.SD[c(1,.N)],Species] ## primera y última fila de cada grupo
##      Species Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1:     setosa          5.1         3.5          1.4         0.2
## 2:     setosa          5.0         3.3          1.4         0.2
## 3: versicolor          7.0         3.2          4.7         1.4
## 4: versicolor          5.7         2.8          4.1         1.3
## 5:  virginica          6.3         3.3          6.0         2.5
## 6:  virginica          5.9         3.0          5.1         1.8Y dentro de SD podemos hacer aplicar funciones usando la función vectorizada lapply():
.SDcols especifica las columnas de la data.table que se incluyen en .SD. Por lo tanto, si queremos sacar la media de las variables “Sepal.Width”, “Sepal.Length” y “Petal.Length” por especies, podemos elegir trabajar sólo con esas columnas usando .SDcols:
7.2.4.4 .GRP
.GRP en j nos da la indexación de los grupos que tenemos.
IRIS[ , i := .GRP, by = Species]
IRIS
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species i col
##   1:          5.1         3.5          1.4         0.2    setosa 1   A
##   2:          4.9         3.0          1.4         0.2    setosa 1   B
##   3:          4.7         3.2          1.3         0.2    setosa 1   A
##   4:          4.6         3.1          1.5         0.2    setosa 1   B
##   5:          5.0         3.6          1.4         0.2    setosa 1   A
##  ---                                                                  
## 146:          6.7         3.0          5.2         2.3 virginica 3   B
## 147:          6.3         2.5          5.0         1.9 virginica 3   A
## 148:          6.5         3.0          5.2         2.0 virginica 3   B
## 149:          6.2         3.4          5.4         2.3 virginica 3   A
## 150:          5.9         3.0          5.1         1.8 virginica 3   B
# o 
IRIS[ , i := .GRP, by = .(Species,col)]
IRIS
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species i col
##   1:          5.1         3.5          1.4         0.2    setosa 1   A
##   2:          4.9         3.0          1.4         0.2    setosa 2   B
##   3:          4.7         3.2          1.3         0.2    setosa 1   A
##   4:          4.6         3.1          1.5         0.2    setosa 2   B
##   5:          5.0         3.6          1.4         0.2    setosa 1   A
##  ---                                                                  
## 146:          6.7         3.0          5.2         2.3 virginica 6   B
## 147:          6.3         2.5          5.0         1.9 virginica 5   A
## 148:          6.5         3.0          5.2         2.0 virginica 6   B
## 149:          6.2         3.4          5.4         2.3 virginica 5   A
## 150:          5.9         3.0          5.1         1.8 virginica 6   B7.2.5 Algunos ejercicios
7.2.5.1 Base de datos de juguete
Volvemos al paquete nycflights13 y la base de datos data.frame flights.
Utiliza data.table() para responder a las siguientes preguntas:
- ¿Cuantos vuelos se realizan en total cada mes?
 - ¿Qué aeropuerto acumula el mayor número de salidas de vuelos en todo el año?
 - ¿Qué compañía acumula el mayor número de salida de vuelos en los meses de verano (jun-sep.)?
 
Lo primero que debemos hacer es convertir la tabla a formato data.table(), i.e.:
7.2.5.2 Nuestra base de datos
Cargar los datos “Siniestros” e “HistoricosSiniestros”, y poner todas las variables como queremos.
Para poner bien las fechas, recordad como se nombran variables en R y el paquete
anytime. Si teneis una base de datos enorme, la funciónanytime()puedee ser un poco lenta. El paquetefasttimees el más eficiente, pero puede ser complicado de usar dependiendo el formato de fecha/hora que tengamos.Crear la variable “Mes_FX_FACTURA”. Recordad el paquete
lubridate.En “HistoricosSiniestros” sacar el último registro de todos los CO_registro
Agrupar las sumas garantizadas por més de declaración
Agrupar las sumas garantizadas por día de declaración a partir del 5 de agosto
Ordenar por día el resultado
Hacedme una gráfica para ver la suma garantizada
7.3 Concatenar
Como ya hemos visto, en data.table podemos concatenar acciones con diferentes [] seguidos:
(DT <- data.table(V1=c(1L,2L), V2=LETTERS[1:3],  V3=round(rnorm(4),4),V4=1:12))
##     V1 V2      V3 V4
##  1:  1  A  1.0963  1
##  2:  2  B -0.9033  2
##  3:  1  C -1.1891  3
##  4:  2  A  1.0650  4
##  5:  1  B  1.0963  5
##  6:  2  C -0.9033  6
##  7:  1  A -1.1891  7
##  8:  2  B  1.0650  8
##  9:  1  C  1.0963  9
## 10:  2  A -0.9033 10
## 11:  1  B -1.1891 11
## 12:  2  C  1.0650 12
DT[,V4.cumsum:=cumsum(V4)]
DT
##     V1 V2      V3 V4 V4.cumsum
##  1:  1  A  1.0963  1         1
##  2:  2  B -0.9033  2         3
##  3:  1  C -1.1891  3         6
##  4:  2  A  1.0650  4        10
##  5:  1  B  1.0963  5        15
##  6:  2  C -0.9033  6        21
##  7:  1  A -1.1891  7        28
##  8:  2  B  1.0650  8        36
##  9:  1  C  1.0963  9        45
## 10:  2  A -0.9033 10        55
## 11:  1  B -1.1891 11        66
## 12:  2  C  1.0650 12        78
DT[,V4.cumsum:=cumsum(V4)] [order(-V3)]
##      V1 V2      V3 V4 V4.cumsum
##  1:  1  A  1.0963  1         1
##  2:  1  B  1.0963  5        15
##  3:  1  C  1.0963  9        45
##  4:  2  A  1.0650  4        10
##  5:  2  B  1.0650  8        36
##  6:  2  C  1.0650 12        78
##  7:  2  B -0.9033  2         3
##  8:  2  C -0.9033  6        21
##  9:  2  A -0.9033 10        55
## 10:  1  C -1.1891  3         6
## 11:  1  A -1.1891  7        28
## 12:  1  B -1.1891 11        66
DT[,V4.cumsum:=cumsum(V4)] [order(-V3)] [V4<6]
##    V1 V2      V3 V4 V4.cumsum
## 1:  1  A  1.0963  1         1
## 2:  1  B  1.0963  5        15
## 3:  2  A  1.0650  4        10
## 4:  2  B -0.9033  2         3
## 5:  1  C -1.1891  3         67.4 JOINS
Se puede usar sintaxis data.table (DT) o la función merge()
Tipos:
- INNER: en DT = 
X[Y, nomatch=0]. Enmerge()= merge(X, Y, all=FALSE) - LEFT OUTER: en DT = 
Y[X]. Enmerge()= merge(X, Y, all.x=TRUE) - RIGHT OUTER: en DT = 
X[Y]. Enmerge()= merge(X, Y, all.y=TRUE) - FULL OUTER: en DT no se puede. En 
merge()= merge(X, Y, all=TRUE) 
7.4.1 INNER
Sólo retorna las filas de df1 que tienen una equivalencia en df2,
7.4.2 LEFT OUTER
Retorna todas las columnas de df1 y df2, pero sólo retorna todas las filas de df1.
7.4.3 RIGHT OUTER
Retorna todas las columnas de df2 y df1, pero sólo retorna todas las filas de df2.
7.4.4 FULL OUTER
Retorna todas las columnas de df1 y df2, y todas las filas de df1 y df2.
7.4.5 setkey() y setkeyv()
Si queremos usar la notación data.table() sin usar el argumento on podemos usar la función setkey() para decirle a cada “data.table” cual es la “clave” de la base de datos:
df1 <- data.table(x = c("X", "Z"), y = 2:1)
df2 <- data.table(x = c("X", "V"), a = 10, b = "a")
setkey(df1,x)
setkey(df2,x)
df1[df2]
##    x  y  a b
## 1: V NA 10 a
## 2: X  2 10 a
df2[df1]
##    x  a    b y
## 1: X 10    a 2
## 2: Z NA <NA> 1Y ahora, la selección de filas también es directa en base a la “key”
Si queremos pasarle varias columnas para ordenar, usaremos la función setkeyv()
7.4.6 ANTI JOIN
(df1 <- data.table(V1 = c(1, 1, 3, 4), V2 = 1:4))
##    V1 V2
## 1:  1  1
## 2:  1  2
## 3:  3  3
## 4:  4  4
(df2 <- data.table(V1 = c(1, 1, 2), V3 = c("a", "b", "a")))
##    V1 V3
## 1:  1  a
## 2:  1  b
## 3:  2  a
df2[!df1,,on=c("V1")]
##    V1 V3
## 1:  2  a
# y del otro lado
df1[!df2,,on=c("V1")]
##    V1 V2
## 1:  3  3
## 2:  4  47.5 Funciones interesantes
7.5.1 Familia set*()
7.5.1.1 Renombrar variables setnames()
setnames(IRIS, "sepal_area", "Area_de_Sepalo")
IRIS[1:2]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species i col Area_de_Sepalo petal_area
## 1:          5.1         3.5          1.4         0.2  setosa 1   A          17.85       0.28
## 2:          4.9         3.0          1.4         0.2  setosa 1   B          14.70       0.28“sepal_area” pasa a llamarse “Area_de_Sepalo” :)
7.5.1.2 Reordenar columnas setcolorder()
7.5.1.3 Ordenar con setorder() y setorderv()
setorder(IRIS, "Petal.Width") ## ordenar por "Petal.Width"
IRIS[1:5]
##    Species Area_de_Sepalo Sepal.Length Sepal.Width Petal.Length Petal.Width i col petal_area
## 1:  setosa          15.19          4.9         3.1          1.5         0.1 1   B       0.15
## 2:  setosa          14.40          4.8         3.0          1.4         0.1 1   A       0.14
## 3:  setosa          12.90          4.3         3.0          1.1         0.1 1   B       0.11
## 4:  setosa          21.32          5.2         4.1          1.5         0.1 1   A       0.15
## 5:  setosa          17.64          4.9         3.6          1.4         0.1 1   B       0.14
setorderv(IRIS, c("Petal.Length","Petal.Width")) ## ordenar por dos variables
IRIS[1:5]
##    Species Area_de_Sepalo Sepal.Length Sepal.Width Petal.Length Petal.Width i col petal_area
## 1:  setosa          16.56          4.6         3.6          1.0         0.2 1   A       0.20
## 2:  setosa          12.90          4.3         3.0          1.1         0.1 1   B       0.11
## 3:  setosa          23.20          5.8         4.0          1.2         0.2 1   A       0.24
## 4:  setosa          16.00          5.0         3.2          1.2         0.2 1   B       0.24
## 5:  setosa          15.04          4.7         3.2          1.3         0.2 1   A       0.267.5.1.4 Ordenar con setkey() y setkeyv()
Como ya vimos antes, estas funciones, ordenan de forma “oficial” los datos.
setkey(IRIS, "Petal.Width") ## ordenar por "Petal.Width"
str(IRIS)
## Classes ‘data.table’ and 'data.frame':   150 obs. of  9 variables:
##  $ Species       : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ Area_de_Sepalo: num  12.9 14.4 17.6 15.2 21.3 ...
##  $ Sepal.Length  : num  4.3 4.8 4.9 4.9 5.2 4.6 5.8 5 4.7 5.5 ...
##  $ Sepal.Width   : num  3 3 3.6 3.1 4.1 3.6 4 3.2 3.2 3.5 ...
##  $ Petal.Length  : num  1.1 1.4 1.4 1.5 1.5 1 1.2 1.2 1.3 1.3 ...
##  $ Petal.Width   : num  0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.2 ...
##  $ i             : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ col           : chr  "B" "A" "B" "B" ...
##  $ petal_area    : num  0.11 0.14 0.14 0.15 0.15 0.2 0.24 0.24 0.26 0.26 ...
##  - attr(*, ".internal.selfref")=<externalptr> 
##  - attr(*, "sorted")= chr "Petal.Width"
setkeyv(IRIS, c("Petal.Length","Petal.Width")) ## ordenar por dos variables
str(IRIS)
## Classes ‘data.table’ and 'data.frame':   150 obs. of  9 variables:
##  $ Species       : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ Area_de_Sepalo: num  16.6 12.9 23.2 16 15 ...
##  $ Sepal.Length  : num  4.6 4.3 5.8 5 4.7 5.5 4.4 4.4 5 4.5 ...
##  $ Sepal.Width   : num  3.6 3 4 3.2 3.2 3.5 3 3.2 3.5 2.3 ...
##  $ Petal.Length  : num  1 1.1 1.2 1.2 1.3 1.3 1.3 1.3 1.3 1.3 ...
##  $ Petal.Width   : num  0.2 0.1 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 ...
##  $ i             : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ col           : chr  "A" "B" "A" "B" ...
##  $ petal_area    : num  0.2 0.11 0.24 0.24 0.26 0.26 0.26 0.26 0.39 0.39 ...
##  - attr(*, ".internal.selfref")=<externalptr> 
##  - attr(*, "sorted")= chr [1:2] "Petal.Length" "Petal.Width"7.5.2 fcase
“CASE” - “WHEN” de data.table. Funciona de esta manera: fcase(test, TRUE, test, TRUE, ..., default=NA)
Volvemos a la base de datos “gapminder”. Vamos a calificar entre países buenos y malos en base a su esperanza de vida.
df <- gapminder
setDT(df)
df[,.(fcase(lifeExp > mean(lifeExp),"good",
            lifeExp < mean(lifeExp),"bad"))]
##         V1
##    1:  bad
##    2:  bad
##    3:  bad
##    4:  bad
##    5:  bad
##   ---     
## 1700: good
## 1701: good
## 1702:  bad
## 1703:  bad
## 1704:  bad
df[,.(fcase(lifeExp > mean(lifeExp),"good",
            default = "bad"))]
##         V1
##    1:  bad
##    2:  bad
##    3:  bad
##    4:  bad
##    5:  bad
##   ---     
## 1700: good
## 1701: good
## 1702:  bad
## 1703:  bad
## 1704:  badY si queremos poner más de una condición:
df[,.(fcase(lifeExp > mean(lifeExp) & gdpPercap > mean(gdpPercap),"good",
            lifeExp < mean(lifeExp) & gdpPercap < mean(gdpPercap),"bad",
            default="medium"))]
##           V1
##    1:    bad
##    2:    bad
##    3:    bad
##    4:    bad
##    5:    bad
##   ---       
## 1700: medium
## 1701: medium
## 1702:    bad
## 1703:    bad
## 1704:    bad7.5.2.1 Ejercicio
Cread una nueva columna con el calificativo “good” or “bad” en base a la esperanza de vida.
7.5.3 fifelse
Funciona de esta manera: fifelse(test, yes, no, na=NA)
df[,.(fifelse(lifeExp > mean(lifeExp),"good","bad"))]
##         V1
##    1:  bad
##    2:  bad
##    3:  bad
##    4:  bad
##    5:  bad
##   ---     
## 1700: good
## 1701: good
## 1702:  bad
## 1703:  bad
## 1704:  bad7.5.3.1 Ejercicio
Poned el calificativo “good” or “bad” comparando las medias de esperanza de vida de cada continenete para 2007. Osea, usad By = continent
7.5.4 rbindlist
Funciona de esta manera: rbindlist( l , use.names = TRUE, fill = FALSE)
Argumentos:
l: una lista que contiene objetos data.table, data.frame o lista.use.names:TRUEjunta por los nombres de las columnas que hacen “match”.FALSElas junta por posición.fill:TRUErellena usando NAs.
Tablas con las mismas variables
(DT1 = data.table(A=1:3,B=letters[1:3]))
##    A B
## 1: 1 a
## 2: 2 b
## 3: 3 c
(DT2 = data.table(A=4:5,B=letters[4:5]))
##    A B
## 1: 4 d
## 2: 5 e
l = list(DT1,DT2)
rbindlist(l)
##    A B
## 1: 1 a
## 2: 2 b
## 3: 3 c
## 4: 4 d
## 5: 5 eTablas con variables diferentes
7.5.5 duplicated
Esta función nos da un vector lógico sobre las filas que hay duplicadas
Funciona de esta manera: duplicated(x, fromLast=FALSE, by=seq_along(x), ...)
x: una data.table.fromLast: dirección en la que te dice la observación que se duplica.by: las variables en las que fijarse para ver duplicados.
(DT <- data.table(A = rep(1:3, each=4), B = rep(1:4, each=3),
                  C = rep(1:2, 6), key = "A,B"))
##     A B C
##  1: 1 1 1
##  2: 1 1 2
##  3: 1 1 1
##  4: 1 2 2
##  5: 2 2 1
##  6: 2 2 2
##  7: 2 3 1
##  8: 2 3 2
##  9: 3 3 1
## 10: 3 4 2
## 11: 3 4 1
## 12: 3 4 2
duplicated(DT)
##  [1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE
duplicated(DT, by="B")
##  [1] FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE
duplicated(DT, by=c("A", "C"))
##  [1] FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE7.5.6 unique
Funciona igual que duplicated, pero nos da la DT sin duplicados
unique(DT)
##     A B C
##  1: 1 1 1
##  2: 1 1 2
##  3: 1 2 2
##  4: 2 2 1
##  5: 2 2 2
##  6: 2 3 1
##  7: 2 3 2
##  8: 3 3 1
##  9: 3 4 2
## 10: 3 4 1
unique(DT, by="B")
##    A B C
## 1: 1 1 1
## 2: 1 2 2
## 3: 2 3 1
## 4: 3 4 2
unique(DT, by=c("A", "C"))
##    A B C
## 1: 1 1 1
## 2: 1 1 2
## 3: 2 2 1
## 4: 2 2 2
## 5: 3 3 1
## 6: 3 4 27.5.7 uniqueN
Esta función nos da el número de niveles diferentes en la variable. Funciona muy parecido a unique
7.5.8 between
Esta función nos da un vector lógico. TRUE si el valor está entre los valores que proporcionemos (lower <= x & x <= upper).
Funciona de esta manera: between(x, lower, upper, incbounds=TRUE)
x: cualquier variable a la que le podamos aplicar un<=.lower: el corte por debajo.upper: el corte por encima.
También puede usarse%between%
7.5.9 fsort
Esta función nos ordena un vector en orden ascendente os descendente:
Funciona de esta manera: fsort(x, decreasing = FALSE, na.last = FALSE)
x: un vectordecreasing:TRUEordena de forma decreciente.FALSE, ascendiente.na.last: donde ponemos los NA.TRUEal final,FALSEal principio.
(x=runif(10))
##  [1] 0.1859589 0.8206501 0.7289161 0.2601126 0.2932034 0.4763283 0.6727095
##  [8] 0.3047416 0.9650763 0.9364433
fsort(x)
##  [1] 0.1859589 0.2601126 0.2932034 0.3047416 0.4763283 0.6727095 0.7289161
##  [8] 0.8206501 0.9364433 0.9650763
fsort(x,decreasing = T)
##  [1] 0.9650763 0.9364433 0.8206501 0.7289161 0.6727095 0.4763283 0.3047416
##  [8] 0.2932034 0.2601126 0.18595897.5.10 like
Esta función nos busca secuencias de letras (strings) en el vector. Se usa para vectores de tipo nombre generalmente
Funciona de esta manera: like(vector, pattern, ignore.case = FALSE)
vector: pues eso, un vector.pattern: el patrón de letras que queremos buscar
ignore.case: para ver si importa si es mayúscula o no.
DT = data.table(Name=c("Mary","George","Martha","Manuel"), 
                Salary=c(2,3,4,17))
DT[like(Name,"Ma")]
##      Name Salary
## 1:   Mary      2
## 2: Martha      4
## 3: Manuel     17
DT[like(Name,"ma")]
## Empty data.table (0 rows and 2 cols): Name,Salary
DT[like(Name,"ma",ignore.case=T)]
##      Name Salary
## 1:   Mary      2
## 2: Martha      4
## 3: Manuel     17
DT[like(Name,"mar",ignore.case=T)]
##      Name Salary
## 1:   Mary      2
## 2: Martha      47.5.11 rowid y rowidv
Esta función genera IDs differentes para cada fila dentro de un grupo.
(DT = data.table(x=c(20,10,10,30,30,20), y=c("a", "a", "a", "b", "b", "b"), z=1:6+.1))
##     x y   z
## 1: 20 a 1.1
## 2: 10 a 2.1
## 3: 10 a 3.1
## 4: 30 b 4.1
## 5: 30 b 5.1
## 6: 20 b 6.1
rowid(DT$x) 
## [1] 1 1 2 1 2 2
rowidv(DT, cols="x") 
## [1] 1 1 2 1 2 2
rowid(DT$x, prefix="grupo") # prefijo 
## [1] "grupo1" "grupo1" "grupo2" "grupo1" "grupo2" "grupo2"
rowid(DT$x, DT$y) 
## [1] 1 1 2 1 2 1
rowidv(DT, cols=c("x","y")) 
## [1] 1 1 2 1 2 1
DT[, id := rowid(x,y)]
##     x y id
## 1: 20 a  1
## 2: 10 a  1
## 3: 10 a  2
## 4: 30 b  1
## 5: 30 b  2
## 6: 20 b  1