Skip to content

[R-es] Ayuda por data.table.

2 messages · Javier Villacampa González, Carlos Ortega

#
Hola buenas,

hoy me preguntaban que como convertir todas las mayusculas de todas las
columnas de un data.frame. Buscando soluciones me han surgido multiples
dudas.

 ###########################
Pregunta 1: ¿Cómo funciona := respocto <-?
¿por qué cambia en varios data tables un valor mienstras que el otro no lo
hace?
¿Se puede evitar?
 ###########################

N <- 10 # numero de checks
n <- 10
DF <- data.frame(V1 = sample(x = letters, size = n, replace = T) ,
                 V2 = sample(x = letters, size = n, replace = T) ,
stringsAsFactors = F)


# 1 asginacion clásica ----------------------------------------------------
DT <- DF %>% data.table()
DT2 <- DT
DT2$V1 <- DT2$V1 %>% toupper
DT2
DT  # Todo Ok



# 2 con := ----------------------------------------------------------------
DT <- DF %>% data.table()
DT2 <- DT
DT2[ , V1 := V1 %>% toupper]
DT2
DT  # Cambia ambos ¿Por qué?

 ###########################
Pregunta 2:  Soluciones para convertir todas las columnas a mayusculas
¿Existen otras mejores? ¿Por qué la asignación base sale la mejor cuando
los bucles deberían ser la peor opcion?
###########################

library(dplyr)
library(data.table)
library(microbenchmark)

N <- 100
n <- 10
dt <- data.table(sample(x = letters, size = n, replace = T) ,
                 sample(x = letters, size = n, replace = T) )

# Opcion 1a sapply
sapply(X = dt,FUN =  toupper)

# Opcion 1b lapply
lapply(X = dt,FUN =  toupper) %>% data.frame

# Opcion 1c lapply
apply(X = dt, MARGIN = 2,FUN =  toupper)


#  ------------------------------------------------------------------------

# Opcion 2 data table. Más rapido cuando los conjuntos son grandes

NAMES <- names(dt)
dt2 <-dt

dt[ , (NAMES) := lapply(X = .SD, FUN = toupper), .SDcol = NAMES]

dt <- dt2
# Opcion 3 data table. Más rapido cuando los conjuntos son grandes
dt %>% mutate_each(funs = funs(toupper) )



#  ------------------------------------------------------------------------
# Comparaciones C
N <- 100 # numero de checks
n <- 10e5
DF <- data.frame(V1 = sample(x = letters, size = n, replace = T) ,
                 V2 = sample(x = letters, size = n, replace = T) ,
stringsAsFactors = F)
DT <- data.table(DF)

NAMES <- names(DF)
times <- microbenchmark(
  sapply = DF2 <- sapply(X = DF,FUN =  toupper) ,
  lapply = DF2 <- lapply(X = DF,FUN =  toupper) %>% data.frame,
  apply = DF2 <- apply(X = DF, MARGIN = 2,FUN =  toupper),
  dplyr = DF %>% mutate_each(funs = funs(toupper) )  ,
  data.table =
    DT[ , (NAMES) := lapply(X = .SD, FUN = toupper), .SDcol = NAMES] ,
  basicFOR = {
    for(i in 1: ncol(DF)){
      DF[ , i ] <- DF[ , i ] %>% toupper
    }
  },
  data.tableFOR = {
    for(i in names(DT)){
      DT[ , V1 := V1 %>% toupper]
      DT[ , V2 := V2 %>% toupper]
    }
  },
  times = N, unit = "s")

times %>% print -> times2
times2[ order(times2$median, decreasing = F), ]


# > times2[ order(times2$median, decreasing = F), ]
# expr       min        lq      mean    median        uq       max neval
cld
# 4         dplyr 0.1492257 0.1694823 0.2155098 0.2037122 0.2288146
0.4119565   100 ab
# 6      basicFOR 0.1498588 0.1715156 0.2099023 0.2052561 0.2294035
0.4420238   100 a
# 5    data.table 0.1560987 0.1701567 0.2322289 0.2194231 0.2690364
0.4829464   100 ab
# 2        lapply 0.2239878 0.2565161 0.3288909 0.3034968 0.3578117
0.6619332   100  bc
# 3         apply 0.2396120 0.2809439 0.3578056 0.3280944 0.4196089
0.6453446   100   c
# 7 data.tableFOR 0.3176318 0.3719481 0.4798864 0.4782654 0.5695964
0.8311082   100    d
# 1        sapply 1.2189397 1.4028805 2.1926634 2.4061735 2.6853981
4.8600199   100     e


--
#
Hola Javier,

varias orientaciones:

   - La asignación "DT2 <- DT" no es la forma de compiar un data.table.
      - Para copiar data.tables, existe una función específica para ello
      "copy()". Mira la ayuda de la función para más aclaraciones.
   - En cuanto al rendimiento de data.table respecto a la función básica
   para cambiar a mayúsculas, haría la prueba sin la asignación de "%>%".
   - Sí, la aplicas en los dos casos por lo que no debiera de afectar, pero
      no lo tengo tan claro en el caso de data.table. No he hecho la prueba, es
      una sospecha. Puedes aplicar directamente la función "toupper()" a la
      columna.
      - También en data.table, prueba a crear "setkey()" sobre la columna
      que vas a modificar (V1) antes de hacer el cambio, también creo
que ayudará.


Saludos,
Carlos Ortega
www.qualityexcellence.es

El 1 de octubre de 2015, 16:05, Javier Villacampa González <
javier.villacampa.gonzalez en gmail.com> escribió: