Hola lista, tengo una base de datos muy grande de un datalogger. Consiste en un vector con 0's y 1's, y tengo que ver cuando hay 600 o más unos seguidos. Se me ocurrió hacerlo con un loop for. Pero tarda demasiado. También intente usar which para que seleccione solo los 1 para empezar a sumar pero no hay gran diferencia. A alguien se le ocurre alguna solución para hacerlo más rápido? Acá está el código con los datos de prueba: test<-rep(c(rep(0,5),rep(1,601),rep(0,100),rep(1,100),rep(0,3),rep(1,200),rep(0,300),rep(1,1000)),100) loop<-numeric() for (i in 1:length(test)) { loop[i]<-sum(test[i:(i+600)]) } loop2<-numeric() for (i in which(test==1)) { loop2[i]<-sum(test[i:(i+600)]) } Muchas gracias a todos los que contesten. Luciano
Hola Luciano. Mira la función ''rle''. Creo que te debería servir. Un saludo. Javier Muñoz. 2009/11/2 Luciano Selzer <luciano.selzer@gmail.com>> Hola lista, tengo una base de datos muy grande de un datalogger. > Consiste en un vector con 0''s y 1''s, y tengo que ver cuando hay 600 o > más unos seguidos. Se me ocurrió hacerlo con un loop for. Pero tarda > demasiado. También intente usar which para que seleccione solo los 1 > para empezar a sumar pero no hay gran diferencia. A alguien se le > ocurre alguna solución para hacerlo más rápido? > > Acá está el código con los datos de prueba: > > > test<-rep(c(rep(0,5),rep(1,601),rep(0,100),rep(1,100),rep(0,3),rep(1,200),rep(0,300),rep(1,1000)),100) > loop<-numeric() > for (i in 1:length(test)) { > loop[i]<-sum(test[i:(i+600)]) > } > > loop2<-numeric() > for (i in which(test==1)) { > loop2[i]<-sum(test[i:(i+600)]) > } > > > > Muchas gracias a todos los que contesten. > Luciano > > _______________________________________________ > R-help-es mailing list > R-help-es@r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es >[[alternative HTML version deleted]]
Hola Luciano: no se es la más elegante de las soluciones pero es bastante más rápida que los loops, names(test) <- 1:length(test) test0 <- test[test==0] filas <- as.numeric(names(test0)) names(test0)[c(names(test0)[1]>600,diff(filas)>600)] esta última sentencia te da los nombres de las filas donde antes hubo más de 600 unos seguidos Saludos Gabriela ----- Original Message ----- From: "Luciano Selzer" <luciano.selzer en gmail.com> To: <r-help-es en r-project.org> Sent: Monday, November 02, 2009 9:53 AM Subject: [R-es] Optimizar código Hola lista, tengo una base de datos muy grande de un datalogger. Consiste en un vector con 0's y 1's, y tengo que ver cuando hay 600 o más unos seguidos. Se me ocurrió hacerlo con un loop for. Pero tarda demasiado. También intente usar which para que seleccione solo los 1 para empezar a sumar pero no hay gran diferencia. A alguien se le ocurre alguna solución para hacerlo más rápido? Acá está el código con los datos de prueba: test<-rep(c(rep(0,5),rep(1,601),rep(0,100),rep(1,100),rep(0,3),rep(1,200),rep(0,300),rep(1,1000)),100) loop<-numeric() for (i in 1:length(test)) { loop[i]<-sum(test[i:(i+600)]) } loop2<-numeric() for (i in which(test==1)) { loop2[i]<-sum(test[i:(i+600)]) } Muchas gracias a todos los que contesten. Luciano _______________________________________________ R-help-es mailing list R-help-es en r-project.org https://stat.ethz.ch/mailman/listinfo/r-help-es ___________________________________________________________________________ Aviso: ==== El contenido del presente e-mail y sus posibles adjuntos pertenecen al INTA y pueden contener información confidencial. Si usted no es el destinatario original de este mensaje y por este medio pudo acceder a dicha información, por favor solicitamos contactar al remitente y eliminar el mensaje de inmediato. Se encuentra prohibida la divulgación, copia, distribución o cualquier otro uso de la información contenida en el presente e-mail por parte de personas distintas al destinatario. This e-mail contents and its possible attachments belong to INTA and may contain confidential information. If this message was not originally addressed to you, but you have accessed to such information by this means, please contact the sender and eliminate this message immediately. Circulation, copy, distribution, or any other use of the information contained in this e-mail is not allowed on part of those different from the addressee. Antes de imprimir este mensaje, asegúrese de que sea necesario. Proteger el medio ambiente está también en su mano.
Es un "literal". De hecho,> storage.mode( 1 )[1] "double"> storage.mode( 1L )[1] "integer" Imagino que hay ciertas ventajas de eficiencia si se fuerza a R a interpretar un número de una determinada forma para evitar tener que realizar conversiones internas. Un saludo, Carlos J. Gil Bellosta http://www.datanalytics.com 2009/11/2 Luciano Selzer <luciano.selzer en gmail.com>:> Hola, que tal? Una pregunta que quizá suene de principiante, pero no > lo vi explicado en ningún libro que leí. Que significa el 0L ó 1L? > Luciano > > > > El día 2 de noviembre de 2009 13:59, Carlos J. Gil Bellosta > <gilbellosta en gmail.com> escribió: >> Hola, ¿qué tal? >> >> Y, abundando en la recomendación de la función rle, si la eficiencia >> es un criterio crítico, uno siempre puede ver el código de dicha >> función y extraer de él la parte relevante. En este caso: >> >> y <- x[-1L] != x[-n] >> y <- c(which(y), n) >> if( any( diff(c(0L, y) ) > 600 ) ) etc. >> >> Un saludo, >> >> Carlos J. Gil Bellosta >> http://www.datanalytics.com >> >> El día 2 de noviembre de 2009 14:12, Javier Muñoz >> <javimunozlara en gmail.com> escribió: >>> Hola Luciano. >>> >>> Mira la función 'rle'. >>> >>> Creo que te debería servir. >>> >>> Un saludo. >>> >>> Javier Muñoz. >>> >>> 2009/11/2 Luciano Selzer <luciano.selzer en gmail.com> >>> >>>> Hola lista, tengo una base de datos muy grande de un datalogger. >>>> Consiste en un vector con 0's y 1's, y tengo que ver cuando hay 600 o >>>> más unos seguidos. Se me ocurrió hacerlo con un loop for. Pero tarda >>>> demasiado. También intente usar which para que seleccione solo los 1 >>>> para empezar a sumar pero no hay gran diferencia. A alguien se le >>>> ocurre alguna solución para hacerlo más rápido? >>>> >>>> Acá está el código con los datos de prueba: >>>> >>>> >>>> test<-rep(c(rep(0,5),rep(1,601),rep(0,100),rep(1,100),rep(0,3),rep(1,200),rep(0,300),rep(1,1000)),100) >>>> loop<-numeric() >>>> for (i in 1:length(test)) { >>>> loop[i]<-sum(test[i:(i+600)]) >>>> } >>>> >>>> loop2<-numeric() >>>> for (i in which(test==1)) { >>>> loop2[i]<-sum(test[i:(i+600)]) >>>> } >>>> >>>> >>>> >>>> Muchas gracias a todos los que contesten. >>>> Luciano >>>> >>>> _______________________________________________ >>>> 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]] >>> >>> >>> _______________________________________________ >>> R-help-es mailing list >>> R-help-es en r-project.org >>> https://stat.ethz.ch/mailman/listinfo/r-help-es >>> >>> >> >
Buenas tardes Luciano, Esta es una solución utilizando rle(): test <- rep(c(rep(0,5),rep(1,601),rep(0,100),rep(1,100),rep(0,3),rep(1,200),rep(0,300),rep(1,1000)),100) names(test) <- 1:length(test) res <- rle(test)$lengths f <- names(res[res > 600]) f[f != ""] Los resultados obtenidos con el programa enviado por Gabriela Cendoya y los proporcionados por rle() son equivalentes: res <- rle(test)$lengths f <- names(res[res > 600]) resjiv <- f[f != ""] test0 <- test[test==0] filas <- as.numeric(names(test0)) resgab <- names(test0)[c(names(test0)[1]>600,diff(filas)>600)] identical(resjiv, resgab) # [1] TRUE Sin embargo, si la eficiencia es relevante y no quieres "hackear" la función rle(), te sugeriría trabajar con la solución enviada por Gabriela. Esto demuestra una vez más que trabajar con funciones vectorizadas es un poco más eficiente. Estos son los tiempos para 100 réplicas: # rle() system.time(replicate(100, { res <- rle(test)$lengths f <- names(res[res > 600]) f[f != ""] } ) ) # user system elapsed # 10.49 0.19 10.69 # Gabriela system.time(replicate(100, { test0 <- test[test==0] filas <- as.numeric(names(test0)) names(test0)[c(names(test0)[1]>600,diff(filas)>600)] } ) ) # user system elapsed # 4.93 0.05 4.98 Espero sea de utilidad, Jorge Ivan Velez 2009/11/2 Luciano Selzer <>> Hola lista, tengo una base de datos muy grande de un datalogger. > Consiste en un vector con 0''s y 1''s, y tengo que ver cuando hay 600 o > más unos seguidos. Se me ocurrió hacerlo con un loop for. Pero tarda > demasiado. También intente usar which para que seleccione solo los 1 > para empezar a sumar pero no hay gran diferencia. A alguien se le > ocurre alguna solución para hacerlo más rápido? > > Acá está el código con los datos de prueba: > > > test<-rep(c(rep(0,5),rep(1,601),rep(0,100),rep(1,100),rep(0,3),rep(1,200),rep(0,300),rep(1,1000)),100) > loop<-numeric() > for (i in 1:length(test)) { > loop[i]<-sum(test[i:(i+600)]) > } > > loop2<-numeric() > for (i in which(test==1)) { > loop2[i]<-sum(test[i:(i+600)]) > } > > > > Muchas gracias a todos los que contesten. > Luciano > > _______________________________________________ > R-help-es mailing list > R-help-es@r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es >[[alternative HTML version deleted]]
Luciano me parece que esto resuelve tu problema test<-rep(c(rep(0,5),rep(1,601),rep(0,100),rep(1,100),rep(0,3),rep(1,200),rep(0,300),rep(1,1000)),100) lookforKones<-function(test,k) { I1=seq(1,length(test),1)[test==0] I1[(I1[2:length(I1)]-I1[1:length(I1)-1])>=k]+1 } #usage lookforKones(test,600) Prof. Julio Di Rienzo Estadística y Biometría FCA- U.N. Córdoba IBS CC Member http://sites.google.com/site/juliodirienzo "Biometry, the active pursuit of biological knowledge by quantitative methods." (R.A. Fisher, 1948) 2009/11/2 Luciano Selzer <luciano.selzer@gmail.com>> Hola lista, tengo una base de datos muy grande de un datalogger. > Consiste en un vector con 0''s y 1''s, y tengo que ver cuando hay 600 o > más unos seguidos. Se me ocurrió hacerlo con un loop for. Pero tarda > demasiado. También intente usar which para que seleccione solo los 1 > para empezar a sumar pero no hay gran diferencia. A alguien se le > ocurre alguna solución para hacerlo más rápido? > > Acá está el código con los datos de prueba: > > > test<-rep(c(rep(0,5),rep(1,601),rep(0,100),rep(1,100),rep(0,3),rep(1,200),rep(0,300),rep(1,1000)),100) > loop<-numeric() > for (i in 1:length(test)) { > loop[i]<-sum(test[i:(i+600)]) > } > > loop2<-numeric() > for (i in which(test==1)) { > loop2[i]<-sum(test[i:(i+600)]) > } > > > > Muchas gracias a todos los que contesten. > Luciano > > _______________________________________________ > R-help-es mailing list > R-help-es@r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es >[[alternative HTML version deleted]]