[R-es] Encontrar la primera columna no NA
Carlos J. Gil Bellosta
cgb en datanalytics.com
Jue Oct 27 18:42:29 CEST 2016
Las operaciones con columnas de data.frames (y sus variantes modernas) son
muy caras. Así que:
t <- Sys.time()
tmp <- (as.matrix(dat))
cols <- col(tmp)
cols[is.na(tmp)] <- Inf
my.cols <- apply(cols, 1, min)
my.values <- tmp[cbind(1:nrow(tmp), my.cols)]
difftime(Sys.time(), t)
Y una pregunta: ¿alguien programa en R base todavía?
Un saludo,
Carlos J. Gil Bellosta
http://www.datanalytics.com
El 27 de octubre de 2016, 18:11, Olivier Nuñez <onunez en unex.es> escribió:
>
> Por último, utilizando la indexación lineal de matriz que propusó luisfo
> en su momento:
>
> > t <- Sys.time()
> > M=as.matrix(dat)
> > index <- which(!is.na(M)) - 1
> > meses<-colnames(M)
> > M2<- data.table(columna=index %/% nrow(M) +1L, jugador=index %% nrow(M)
> +1L , valor=M[index+1L])
> > setkey(M2,jugador,columna)
> > M2[,.(First_month=meses[columna[1]],Value_First_month=
> valor[1]),by=jugador]
> jugador First_month Value_First_month
> 1: 1 Uno 0.93520715
> 2: 2 Uno 0.85930634
> 3: 3 dos 0.13521503
> 4: 4 Uno 0.86996341
> 5: 5 dos 0.65879889
> ---
> 99996: 99996 Uno 0.94728423
> 99997: 99997 Uno 0.24088571
> 99998: 99998 Uno 0.07458581
> 99999: 99999 Uno 0.30535050
> 100000: 100000 Uno 0.54640585
> > difftime( Sys.time(), t)
> Time difference of 0.3299999 secs
> >
> ----- Mensaje original -----
> De: Javier Villacampa González <javier.villacampa.gonzalez en gmail.com>
> Para: Olivier Nuñez <onunez en unex.es>
> CC: R ayuda <r-help-es en r-project.org>
> Enviado: Thu, 27 Oct 2016 17:17:12 +0200 (CEST)
> Asunto: Re: [R-es] Encontrar la primera columna no NA
>
> Hemos mejorado bastante desde el inicio. Pero aun andamos lejos. Igual es
> por el merge que hago. Seguire mirando
> library(microbenchmark)
> N <- 1e1
> tabla <-
> microbenchmark(
> # JVG_dplyr ={
> # dat %>%
> # apply( MARGIN = 1, FUN =
> # function(x){
> # which( !is.na(x) ) %>% min( na.rm = TRUE ) %>%
> return()
> # }
> # )
> # dat[ , First_month := First_month]
> # N_for <- length( unique(First_month ))
> # for( j in 1:N_for){
> # x <- dat[ First_month == j, j, with = FALSE]
> # dat[ First_month == j , Value_First_month := x ]
> # }
> # },
> JVG ={
> dat <-
> data.table( Uno = sample( c(runif(numero) , rep(NA , numero /2e0
> )) , size = numero ) ,
> dos = sample( c(runif(numero) , rep(NA , numero /1e1
> )) , size = numero ) ,
> tres = sample( c(runif(numero) , rep(NA , numero /2e1
> )) , size = numero ) ,
> cuatro = sample( c(runif(numero) , rep(NA , numero /1e2
> )) , size = numero ) ,
> cinco = sample( c(runif(numero) , rep(NA , numero /2e2
> )) , size = numero ) ,
> seis = sample( c(runif(numero) , rep(NA , numero /1e3
> )) , size = numero )
> )
>
> apply(X = dat, MARGIN = 1, FUN =
> function(x){
> return( min( which( !is.na(x) ), na.rm = TRUE ) )
> }
> )
> dat[ , First_month := First_month]
> N_for <- length( unique(First_month ))
> for( j in 1:N_for){
> x <- dat[ First_month == j, j, with = FALSE]
> dat[ First_month == j , Value_First_month := x ]
> }
> },
> Olivier ={
> dat <-
> data.table( Uno = sample( c(runif(numero) , rep(NA , numero /2e0
> )) , size = numero ) ,
> dos = sample( c(runif(numero) , rep(NA , numero /1e1
> )) , size = numero ) ,
> tres = sample( c(runif(numero) , rep(NA , numero /2e1
> )) , size = numero ) ,
> cuatro = sample( c(runif(numero) , rep(NA , numero /1e2
> )) , size = numero ) ,
> cinco = sample( c(runif(numero) , rep(NA , numero /2e2
> )) , size = numero ) ,
> seis = sample( c(runif(numero) , rep(NA , numero /1e3
> )) , size = numero )
> )
> dat[,First_month := apply(X = .SD,MARGIN = 1,FUN = function(x)
> colnames(.SD)[min(which(!is.na(x)))])]
> dat[,Value_First_month := apply(X = .SD,MARGIN = 1,FUN = function(x)
> x[min(which(!is.na(x)))])]
> },
> Olivier2={
> dat <-
> data.table( Uno = sample( c(runif(numero) , rep(NA , numero /2e0
> )) , size = numero ) ,
> dos = sample( c(runif(numero) , rep(NA , numero /1e1
> )) , size = numero ) ,
> tres = sample( c(runif(numero) , rep(NA , numero /2e1
> )) , size = numero ) ,
> cuatro = sample( c(runif(numero) , rep(NA , numero /1e2
> )) , size = numero ) ,
> cinco = sample( c(runif(numero) , rep(NA , numero /2e2
> )) , size = numero ) ,
> seis = sample( c(runif(numero) , rep(NA , numero /1e3
> )) , size = numero )
> )
>
> dat[,jugador:=1:.N]
> dat2=melt(dat,id.vars="jugador")
> setkey(dat2,jugador)
> dat2[,index:=min(which(!is.na(value))),by=jugador]
> dat3 <- dat2[,list(First_month_Olivier
> =variable[index[1]],Value_First_month_Olivier
> =value[index[1]]),by=jugador]
> setkey(x = dat, jugador)
> dat0 <- merge( x = dat, y = dat3, all.x = TRUE, all.y = FALSE)
>
> },
> times = N, unit = "s")
>
> tabla %>% print
> beepr::beep(3)
>
> # Unit: seconds
> # expr min lq mean median uq max
> neval
> # JVG 0.6479002 0.7518933 0.8673007 0.8216553 0.9137195 1.251891
> 10
> # Olivier 2.9568197 3.6663586 3.9364770 3.9069826 4.5619519 4.685842 10
> # Olivier2 1.1316970 1.4463621 1.4735507 1.4874366 1.5681243 1.631713 10
> # E comparativa ------------------------------
> -----------------------------
>
> El 27 de octubre de 2016, 15:39, Olivier Nuñez <onunez en unex.es> escribió:
>
> > Otra solución algo más rapida:
> > > t <- Sys.time()
> > > dat[,jugador:=1:.N]
> > > dat2=melt(dat,id.vars="jugador")
> > > setkey(dat2,jugador)
> > > dat2[,index:=min(which(!is.na(value))),by=jugador]
> > > dat2[,.(First_month=variable[index[1]],Value_First_month=
> > value[index[1]]),by=jugador]
> > jugador First_month Value_First_month
> > 1: 1 Uno 0.93520715
> > 2: 2 Uno 0.85930634
> > 3: 3 dos 0.13521503
> > 4: 4 Uno 0.86996341
> > 5: 5 dos 0.65879889
> > ---
> > 99996: 99996 Uno 0.94728423
> > 99997: 99997 Uno 0.24088571
> > 99998: 99998 Uno 0.07458581
> > 99999: 99999 Uno 0.30535050
> > 100000: 100000 Uno 0.54640585
> > > difftime( Sys.time(), t)
> > Time difference of 1.060787 secs
> >
> >
> > ----- Mensaje original -----
> > De: "Olivier Nuñez" <onunez en unex.es>
> > Para: "Javier Villacampa González" <javier.villacampa.gonzalez en gmail.com
> >
> > CC: "R ayuda" <r-help-es en r-project.org>
> > Enviados: Jueves, 27 de Octubre 2016 15:10:07
> > Asunto: Re: [R-es] Encontrar la primera columna no NA
> >
> > Prueba lo siguiente, no es óptimo, pero creo va bastnate más rapido que
> > los que mencionaste:
> >
> > t <- Sys.time()
> > dat[,First_month := apply(.SD,1,function(x) colnames(.SD)[min(which(!
> is.na
> > (x)))])]
> > dat[,Value_First_month := apply(.SD,1,function(x) x[min(which(!is.na
> > (x)))])]
> > difftime( Sys.time(), t)
> >
> > Time difference of 3.478778 secs
> >
> >
> > ----- Mensaje original -----
> > De: "Javier Villacampa González" <javier.villacampa.gonzalez en gmail.com>
> > Para: "R ayuda" <r-help-es en r-project.org>
> > Enviados: Jueves, 27 de Octubre 2016 13:43:19
> > Asunto: [R-es] Encontrar la primera columna no NA
> >
> > Imaginemos que tenemos una matriz con datos temporales por sujetos.
> > Pongamos que numero de veces que ha jugado una carta en un juego online.
> Y
> > que quiero saber cuantas veces jugo la carta el primer mes que estuvo en
> el
> > juego.
> >
> > Pero claro mi matriz guarda los datos temporalmente de tal manera que:
> >
> > # data.table( Enero = c( 1, 4, NA , NA , NA) , Febrero = c( 2, 6, 1, NA,
> NA
> > ) , Marzo = c( 8,6,7,3, NA) , Abril = c( NA, 15, 5, 6,6 ))
> > # Enero Febrero Marzo Abril
> > # 1: 1 2 8 NA
> > # 2: 4 6 6 15
> > # 3: NA 1 7 5
> > # 4: NA NA 3 6
> > # 5: NA NA NA 6
> > # Suponiendo que cada fila es un jugador
> > # En este caso la solucion debería ser
> > # 1 para el primero que empezó en Enero
> > # 4 para el segundo jugador que empezó en Enero
> > # 1 para el tercero que empezó en Febrero
> > # 3 Para el cuarto que empezó en Marzo
> > # 6 para el quinto que empezó en Abril
> >
> >
> > A alguno se os ocurre una solucion más eficiente que la siguiente. Esto
> > seguro que con data table o dplyr se puede. Ya he quitados los pipes que
> > facilitan la lectura pero que no se llevan bien con data.table. Pero
> estoy
> > seguro que se puede mejorar más.
> >
> > #=======================================================
> > # Como ejemplo de codigo
> > #=======================================================
> > # S Primera solucion ------------------------------
> > ------------------------
> > # First not NA colum per subject
> > library(data.table)
> > library(dplyr)
> > set.seed(123456)
> > numero <- 1e5
> > dat <-
> > data.table( Uno = sample( c(runif(numero) , rep(NA , numero /2e0 )),
> > size = numero ) ,
> > dos = sample( c(runif(numero) , rep(NA , numero /1e1 )),
> > size = numero ) ,
> > tres = sample( c(runif(numero) , rep(NA , numero /2e1 )) ,
> > size = numero ) ,
> > cuatro = sample( c(runif(numero) , rep(NA , numero /1e2 )) ,
> > size = numero ) ,
> > cinco = sample( c(runif(numero) , rep(NA , numero /2e2 )) ,
> > size = numero ) ,
> > seis = sample( c(runif(numero) , rep(NA , numero /1e3 )) ,
> > size = numero )
> > )
> >
> >
> > t <- Sys.time()
> > First_month <-
> > dat %>%
> > apply( MARGIN = 1, FUN =
> > function(x){
> > which( !is.na(x) ) %>% min( na.rm = TRUE ) %>% return()
> > }
> > )
> >
> >
> >
> > First_month %>% table %>% prop.table
> > dat[ , First_month := First_month]
> > N_for <- length( unique(First_month ))
> > for( j in 1:N_for){
> > x <- dat[ First_month == j, j, with = FALSE]
> > dat[ First_month == j , Value_First_month := x ]
> > }
> >
> > dat %>% print
> > # dat %>% summary
> >
> > cat( "===============================\n", difftime( Sys.time(), t,
> units =
> > "min") , " minutos que cuesta \n===============================\n" )
> > beepr::beep(3)
> > # E Primera solucion ------------------------------
> > ------------------------
> >
> >
> >
> >
> > # S comparativa ------------------------------
> > -----------------------------
> > library(microbenchmark)
> > N <- 1e2
> > tabla <-
> > microbenchmark(
> > JVG_dplyr ={ dat %>%
> > apply( MARGIN = 1, FUN =
> > function(x){
> > which( !is.na(x) ) %>% min( na.rm = TRUE ) %>%
> > return()
> > }
> > )
> > },
> > JVG ={
> > apply(X = dat, MARGIN = 1, FUN =
> > function(x){
> > return( min( which( !is.na(x) ), na.rm = TRUE )
> )
> > }
> > )
> > },
> > times = N, unit = "s")
> >
> > tabla %>% print
> > beepr::beep(3)
> >
> > # Unit: seconds
> > # expr min lq mean median uq
> max
> > neval
> > # JVG_dplyr 21.2321152 22.233428 22.9575357 22.5701781 23.444432
> > 26.642730 10
> > # JVG 0.7628928 0.843067 0.9260389 0.8495834 1.027036
> > 1.295868 10
> > # E comparativa ------------------------------
> > -----------------------------
> >
> > --
> >
> > [[alternative HTML version deleted]]
> >
> > _______________________________________________
> > R-help-es mailing list
> > R-help-es en r-project.org
> > https://stat.ethz.ch/mailman/listinfo/r-help-es
> >
> > _______________________________________________
> > R-help-es mailing list
> > R-help-es en r-project.org
> > https://stat.ethz.ch/mailman/listinfo/r-help-es
> >
>
>
>
> --
>
> _______________________________________________
> R-help-es mailing list
> R-help-es en r-project.org
> https://stat.ethz.ch/mailman/listinfo/r-help-es
>
[[alternative HTML version deleted]]
Más información sobre la lista de distribución R-help-es