Francisco Javier
2014-Mar-10 18:19 UTC
[R-es] Frecuencia absoluta acumulada por individuo y por año
Hola, Hola a todos, Os escribo porque no consigo finalizar el script necesario para realizar lo que a continuación planteo. Partiendo de un data frame (2 millones de casos), tengo:> datos2ID FECHA YEAR CANTIDAD 1 100 2005-08-02 2005 1 2 100 2005-10-19 2005 2 3 100 2007-02-09 2007 1 4 100 2007-10-25 2007 1 5 100 2007-10-29 2007 1 6 120 2006-05-11 2006 1 7 120 2006-08-17 2006 5 8 120 2006-10-15 2006 1 9 120 2007-04-16 2007 3 Y desearía las cantidades acumuladas por ID y año, a partir del primer año con registros de cada ID, obteniendo: ID YEAR CANTIDAD 1 100 2005 3 2 100 2006 3 (como en el 2006 no hay datos de ID=100, el acumulado se mantiene) 3 100 2007 6 4 120 2006 7 5 120 2007 10 Hasta ahora sólo he conseguido llegar a esto mediante el paquete data.table:> library(data.table) > datos2 <- data.table(datos2) > datos2 <- datos2[, ACUM.CANTIDAD:=cumsum(CANTIDAD), by = list(ID, YEAR)] > datos2ID FECHA YEAR CANTIDAD ACUM.CANTIDAD 1: 100 2005-08-02 2005 1 1 2: 100 2005-10-19 2005 2 3 3: 100 2007-02-09 2007 1 1 4: 100 2007-10-25 2007 1 2 5: 100 2007-10-29 2007 1 3 6: 120 2006-05-11 2006 1 1 7: 120 2006-08-17 2006 5 6 8: 120 2006-10-15 2006 1 7 9: 120 2007-04-16 2007 3 3 Cualquier ayuda será bienvenida. Muchísimas gracias. [[alternative HTML version deleted]]
"Marcuzzi, Javier Rubén"
2014-Mar-10 19:58 UTC
[R-es] Frecuencia absoluta acumulada por individuo y por año
Estimado Francisco Javier Una posibilidad es utilizar merge, porque usted no obtiene un valor en el año donde no hay información, ID YEAR CANTIDAD 1 100 2005 3 2 100 2006 3 (como en el 2006 no hay datos de ID=100, el acumulado se mantiene) Como es el año 2006, Por eso pasa del 2005 al 2007 ID FECHA YEAR CANTIDAD ACUM.CANTIDAD 1: 100 2005-08-02 2005 1 1 2: 100 2005-10-19 2005 2 3 3: 100 2007-02-09 2007 1 1 4: 100 2007-10-25 2007 1 2 Con merge podría unir las dos tablas. Otra posibilidad puede ser algo como do.call(rbind, by(Dataframe, Dataframe$ID, function(x) colocar la función de suma) Javier Marcuzzi El 10/03/14 15:19, Francisco Javier escribió:> Hola, > > Hola a todos, > Os escribo porque no consigo finalizar el script necesario para realizar lo que a continuación planteo. Partiendo de un data frame (2 millones de casos), tengo: > >> datos2 > ID FECHA YEAR CANTIDAD > 1 100 2005-08-02 2005 1 > 2 100 2005-10-19 2005 2 > 3 100 2007-02-09 2007 1 > 4 100 2007-10-25 2007 1 > 5 100 2007-10-29 2007 1 > 6 120 2006-05-11 2006 1 > 7 120 2006-08-17 2006 5 > 8 120 2006-10-15 2006 1 > 9 120 2007-04-16 2007 3 > > Y desearía las cantidades acumuladas por ID y año, a partir del primer año con registros de cada ID, obteniendo: > ID YEAR CANTIDAD > 1 100 2005 3 > 2 100 2006 3 (como en el 2006 no hay datos de ID=100, el acumulado se mantiene) > 3 100 2007 6 > 4 120 2006 7 > 5 120 2007 10 > > Hasta ahora sólo he conseguido llegar a esto mediante el paquete data.table: >> library(data.table) >> datos2 <- data.table(datos2) >> datos2 <- datos2[, ACUM.CANTIDAD:=cumsum(CANTIDAD), by = list(ID, YEAR)] >> datos2 > ID FECHA YEAR CANTIDAD ACUM.CANTIDAD > 1: 100 2005-08-02 2005 1 1 > 2: 100 2005-10-19 2005 2 3 > 3: 100 2007-02-09 2007 1 1 > 4: 100 2007-10-25 2007 1 2 > 5: 100 2007-10-29 2007 1 3 > 6: 120 2006-05-11 2006 1 1 > 7: 120 2006-08-17 2006 5 6 > 8: 120 2006-10-15 2006 1 7 > 9: 120 2007-04-16 2007 3 3 > > Cualquier ayuda será bienvenida. Muchísimas gracias. > > > > [[alternative HTML version deleted]] > > > > _______________________________________________ > R-help-es mailing list > R-help-es@r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es[[alternative HTML version deleted]]
Si entendí bien lo que quieres quizás esto te sirva: datos2 <- "ID FECHA YEAR CANTIDAD 1 100 2005-08-02 2005 1 2 100 2005-10-19 2005 2 3 100 2007-02-09 2007 1 4 100 2007-10-25 2007 1 5 100 2007-10-29 2007 1 6 120 2006-05-11 2006 1 7 120 2006-08-17 2006 5 8 120 2006-10-15 2006 1 9 120 2007-04-16 2007 3 " midat <- read.table(textConnection(datos2), header=T, as.is = TRUE) res <- within(midat, { ACUM.CANTIDAD <- ave(CANTIDAD, ID, YEAR, FUN = cumsum) }) res # http://stackoverflow.com/questions/14999556/cumsum-using-ddply Daniel Merino El 10 de marzo de 2014, 16:58, "Marcuzzi, Javier Rubén" < javier.ruben.marcuzzi@gmail.com> escribió:> Estimado Francisco Javier > > Una posibilidad es utilizar merge, porque usted no obtiene un valor en > el año donde no hay información, > > ID YEAR CANTIDAD > 1 100 2005 3 > 2 100 2006 3 (como en el 2006 no hay datos de ID=100, el acumulado > se mantiene) > > Como es el año 2006, > > Por eso pasa del 2005 al 2007 > > ID FECHA YEAR CANTIDAD ACUM.CANTIDAD > 1: 100 2005-08-02 2005 1 1 > 2: 100 2005-10-19 2005 2 3 > 3: 100 2007-02-09 2007 1 1 > 4: 100 2007-10-25 2007 1 2 > > > Con merge podría unir las dos tablas. > > Otra posibilidad puede ser algo como > > do.call(rbind, by(Dataframe, Dataframe$ID, function(x) colocar la > función de suma) > > Javier Marcuzzi > > > El 10/03/14 15:19, Francisco Javier escribió: > > Hola, > > > > Hola a todos, > > Os escribo porque no consigo finalizar el script necesario para realizar > lo que a continuación planteo. Partiendo de un data frame (2 millones de > casos), tengo: > > > >> datos2 > > ID FECHA YEAR CANTIDAD > > 1 100 2005-08-02 2005 1 > > 2 100 2005-10-19 2005 2 > > 3 100 2007-02-09 2007 1 > > 4 100 2007-10-25 2007 1 > > 5 100 2007-10-29 2007 1 > > 6 120 2006-05-11 2006 1 > > 7 120 2006-08-17 2006 5 > > 8 120 2006-10-15 2006 1 > > 9 120 2007-04-16 2007 3 > > > > Y desearía las cantidades acumuladas por ID y año, a partir del primer > año con registros de cada ID, obteniendo: > > ID YEAR CANTIDAD > > 1 100 2005 3 > > 2 100 2006 3 (como en el 2006 no hay datos de ID=100, el > acumulado se mantiene) > > 3 100 2007 6 > > 4 120 2006 7 > > 5 120 2007 10 > > > > Hasta ahora sólo he conseguido llegar a esto mediante el paquete > data.table: > >> library(data.table) > >> datos2 <- data.table(datos2) > >> datos2 <- datos2[, ACUM.CANTIDAD:=cumsum(CANTIDAD), by = list(ID, YEAR)] > >> datos2 > > ID FECHA YEAR CANTIDAD ACUM.CANTIDAD > > 1: 100 2005-08-02 2005 1 1 > > 2: 100 2005-10-19 2005 2 3 > > 3: 100 2007-02-09 2007 1 1 > > 4: 100 2007-10-25 2007 1 2 > > 5: 100 2007-10-29 2007 1 3 > > 6: 120 2006-05-11 2006 1 1 > > 7: 120 2006-08-17 2006 5 6 > > 8: 120 2006-10-15 2006 1 7 > > 9: 120 2007-04-16 2007 3 3 > > > > Cualquier ayuda será bienvenida. Muchísimas gracias. > > > > > > > > [[alternative HTML version deleted]] > > > > > > > > _______________________________________________ > > R-help-es mailing list > > R-help-es@r-project.org > > https://stat.ethz.ch/mailman/listinfo/r-help-es > > > [[alternative HTML version deleted]] > > > _______________________________________________ > R-help-es mailing list > R-help-es@r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es > >-- Daniel [[alternative HTML version deleted]]
Carlos Ortega
2014-Mar-10 22:47 UTC
[R-es] Frecuencia absoluta acumulada por individuo y por año
Hola, Crear la suma acumulada, puede hacerse de diferentes formas. Pero rellenar el hueco del año cuando hay dos filas consecutivas con el mismo ID pero diferente año, es donde aparece la complejidad. Esta es una forma de crear la suma acumulada (con sqldf) y de completar ese hueco. El hueco se completa, pero siempre que el salto del año sea de uno, como en el ejemplo de los datos que has incluido. #------------------------------------------------------ Lines <- "ROW ID FECHA YEAR CANTIDAD 1 100 2005-08-02 2005 1 2 100 2005-10-19 2005 2 3 100 2007-02-09 2007 1 4 100 2007-10-25 2007 1 5 100 2007-10-29 2007 1 6 120 2006-05-11 2006 1 7 120 2006-08-17 2006 5 8 120 2006-10-15 2006 1 9 120 2007-04-16 2007 3 " DF <- read.table(textConnection(Lines), header=T, as.is = TRUE) # Consigo el valor acumulado de CANTIDAD agrupado por YEAR y ID library(sqldf) df.tmp <- sqldf("select ID,YEAR, sum(CANTIDAD) as cusum from DF group by ID,YEAR order by ID,YEAR") # Ahora completo el hueco en el año df.new <- 0 for(i in 1:nrow(df.tmp)) { if(i>1) { if(df.tmp$ID[i]==df.tmp$ID[i-1] & (df.tmp$YEAR[i]!=df.tmp$YEAR[i-1]) & df.tmp$YEAR[i]-df.tmp$YEAR[i-1] > 1 ){ #Introduzco la fila anterior que falta df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i]-1 ,df.tmp$cusum[i])) #Introduzco la fila tal cual df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i] ,df.tmp$cusum[i])) } else { df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i] ,df.tmp$cusum[i])) } } else { # i=1 - Copio la fila df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i] ,df.tmp$cusum[i])) } } df.tmp # Arreglo df.new df.new <- df.new[2:nrow(df.new),] row.names(df.new) <- NULL df.new <- as.data.frame(df.new) names(df.new) <- names(df.tmp) df.new #----------------------------- FIN DE PROGRAMA ------------------------- Saludos, Carlos Ortega www.qualityexcellence.es El 10 de marzo de 2014, 19:19, Francisco Javier <iterador10@hotmail.com>escribió:> Hola, > > Hola a todos, > Os escribo porque no consigo finalizar el script necesario para realizar > lo que a continuación planteo. Partiendo de un data frame (2 millones de > casos), tengo: > > > datos2 > ID FECHA YEAR CANTIDAD > 1 100 2005-08-02 2005 1 > 2 100 2005-10-19 2005 2 > 3 100 2007-02-09 2007 1 > 4 100 2007-10-25 2007 1 > 5 100 2007-10-29 2007 1 > 6 120 2006-05-11 2006 1 > 7 120 2006-08-17 2006 5 > 8 120 2006-10-15 2006 1 > 9 120 2007-04-16 2007 3 > > Y desearía las cantidades acumuladas por ID y año, a partir del primer año > con registros de cada ID, obteniendo: > ID YEAR CANTIDAD > 1 100 2005 3 > 2 100 2006 3 (como en el 2006 no hay datos de ID=100, el acumulado > se mantiene) > 3 100 2007 6 > 4 120 2006 7 > 5 120 2007 10 > > Hasta ahora sólo he conseguido llegar a esto mediante el paquete > data.table: > > library(data.table) > > datos2 <- data.table(datos2) > > datos2 <- datos2[, ACUM.CANTIDAD:=cumsum(CANTIDAD), by = list(ID, YEAR)] > > datos2 > ID FECHA YEAR CANTIDAD ACUM.CANTIDAD > 1: 100 2005-08-02 2005 1 1 > 2: 100 2005-10-19 2005 2 3 > 3: 100 2007-02-09 2007 1 1 > 4: 100 2007-10-25 2007 1 2 > 5: 100 2007-10-29 2007 1 3 > 6: 120 2006-05-11 2006 1 1 > 7: 120 2006-08-17 2006 5 6 > 8: 120 2006-10-15 2006 1 7 > 9: 120 2007-04-16 2007 3 3 > > Cualquier ayuda será bienvenida. Muchísimas gracias. > > > > [[alternative HTML version deleted]] > > > _______________________________________________ > R-help-es mailing list > R-help-es@r-project.org > https://stat.ethz.ch/mailman/listinfo/r-help-es > >-- Saludos, Carlos Ortega www.qualityexcellence.es [[alternative HTML version deleted]]
Carlos Ortega
2014-Mar-10 23:49 UTC
[R-es] Frecuencia absoluta acumulada por individuo y por año
Hola, Vaya, en el código que he enviado, cusum no se incrementaba.. Y has indicado que se introduce un año más, con el mismo ID que el anterior y con la misma cantidad acumulada. Pero si el siguiente año es del mismo ID, acumula el valor de la cantidad que hemos introducido en esa fila... Con el siguiente código se resuelve este error y además ya está preparado para contemplar cualquier tipo de salto en años. He modificado un para de años sobre el resultado inicial del sqldf para mostrarlo. El problema de este código es que son dos bucles seguidos...pero resuelve la situación... #---------------------------------------------------------------------- Lines <- "ROW ID FECHA YEAR CANTIDAD 1 100 2005-08-02 2005 1 2 100 2005-10-19 2005 2 3 100 2007-02-09 2007 1 4 100 2007-10-25 2007 1 5 100 2007-10-29 2007 1 6 120 2006-05-11 2006 1 7 120 2006-08-17 2006 5 8 120 2006-10-15 2006 1 9 120 2007-04-16 2007 3 " DF <- read.table(textConnection(Lines), header=T, as.is = TRUE) library(sqldf) df.tmp <- sqldf("select ID,YEAR, sum(CANTIDAD) as cusum from DF group by ID,YEAR order by ID,YEAR") #----------------------- quitar estas filas # Pruebo que el salto en años sea mayor que dos.. # En vez de "100 2007" lo cambio a "100 2008".. df.tmp[2,2] <- c(2008) # Y que la última fila "120 2007" pasa a ser "120 2014" df.tmp[4,2] <- c(2014) #----------------------- quitar filas anteriores #------- Primer bucle para detectar los saltos en los años for(i in 1:nrow(df.tmp)) { if(i==1 ) { df.tmp$difID[i] <- 0 df.tmp$difYE[i] <- 0 } else{ if(df.tmp$ID[i]!=df.tmp$ID[i-1] & (df.tmp$YEAR[i]-df.tmp$YEAR[i-1] < 0)) { df.tmp$difID[i] <- 0 df.tmp$difYE[i] <- 0 } else { df.tmp$difID[i] <- df.tmp$ID[i] - df.tmp$ID[i-1] df.tmp$difYE[i] <- df.tmp$YEAR[i] - df.tmp$YEAR[i-1] } } } df.tmp #------- Segundo bucle para introducir filas en los saltos de años # Introduzco filas cuando el salto de años sea mayor que 2... df.new <- 0 for(i in 1:nrow(df.tmp)) { #Copio la fila tal cual cuando la diferencia en años es 0 o menor que dos. if(df.tmp$difYE[i] < 2) { df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i] ,df.tmp$cusum[i])) } else { # Si la diferencia en años es mayor que dos, ciclo en años y teniendo en cuenta que cusum se acumula... cusum.cont <- df.tmp$cusum[i-1] for(j in 1:(df.tmp$difYE[i]-1) ) { df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i-1]+j ,df.tmp$cusum[i-1])) cusum.cont <- cusum.cont + df.tmp$cusum[i-1] } # Y tras ciclar copio la fila en la que estaba df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i] ,df.tmp$cusum[i]+cusum.cont)) } } df.tmp df.new <- df.new[2:nrow(df.new),] row.names(df.new) <- NULL df.new <- as.data.frame(df.new) names(df.new) <- c('ID', 'YEAR','CUSUM') df.new #--------------------------------------------------------------------- En R el resultado es este: A) El data.frame resultado del sqldf pero *manipulado*.> df.tmp ID YEAR cusum difID difYE1 100 2005 3 0 0 2 100 2008 3 0 3 3 120 2006 7 0 0 4 120 2014 3 0 8 B) Resultado final con el procesado. Incluyendo años que faltan y arrastrando cusum incluso para esos años añadidos...> df.new ID YEAR CUSUM1 100 2005 3 2 100 2006 3 3 100 2007 3 4 100 2008 12 5 120 2006 7 6 120 2007 7 7 120 2008 7 8 120 2009 7 9 120 2010 7 10 120 2011 7 11 120 2012 7 12 120 2013 7 13 120 2014 59 Saludos, Carlos Ortega www.qualityexcellence.es El 10 de marzo de 2014, 23:47, Carlos Ortega <cof@qualityexcellence.es>escribió:> Hola, > > Crear la suma acumulada, puede hacerse de diferentes formas. > Pero rellenar el hueco del año cuando hay dos filas consecutivas con el > mismo ID pero diferente año, es donde aparece la complejidad. > > Esta es una forma de crear la suma acumulada (con sqldf) y de completar > ese hueco. > El hueco se completa, pero siempre que el salto del año sea de uno, como > en el ejemplo de los datos que has incluido. > > #------------------------------------------------------ > Lines <- "ROW ID FECHA YEAR CANTIDAD > > 1 100 2005-08-02 2005 1 > 2 100 2005-10-19 2005 2 > 3 100 2007-02-09 2007 1 > 4 100 2007-10-25 2007 1 > 5 100 2007-10-29 2007 1 > 6 120 2006-05-11 2006 1 > 7 120 2006-08-17 2006 5 > 8 120 2006-10-15 2006 1 > 9 120 2007-04-16 2007 3 > " > > DF <- read.table(textConnection(Lines), header=T, as.is = TRUE) > > # Consigo el valor acumulado de CANTIDAD agrupado por YEAR y ID > library(sqldf) > df.tmp <- sqldf("select ID,YEAR, sum(CANTIDAD) as cusum from DF group by > ID,YEAR order by ID,YEAR") > > # Ahora completo el hueco en el año > df.new <- 0 > for(i in 1:nrow(df.tmp)) { > > if(i>1) { > if(df.tmp$ID[i]==df.tmp$ID[i-1] & > (df.tmp$YEAR[i]!=df.tmp$YEAR[i-1]) & df.tmp$YEAR[i]-df.tmp$YEAR[i-1] > 1 ){ > > #Introduzco la fila anterior que falta > df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i]-1 > ,df.tmp$cusum[i])) > > #Introduzco la fila tal cual > df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i] > ,df.tmp$cusum[i])) > > } else { > df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i] > ,df.tmp$cusum[i])) > } > } else { > # i=1 - Copio la fila > df.new <- rbind(df.new, c(df.tmp$ID[i] , df.tmp$YEAR[i] > ,df.tmp$cusum[i])) > } > > } > > df.tmp > # Arreglo df.new > df.new <- df.new[2:nrow(df.new),] > row.names(df.new) <- NULL > df.new <- as.data.frame(df.new) > names(df.new) <- names(df.tmp) > df.new > > > #----------------------------- FIN DE PROGRAMA ------------------------- > > > Saludos, > Carlos Ortega > www.qualityexcellence.es > > > El 10 de marzo de 2014, 19:19, Francisco Javier <iterador10@hotmail.com>escribió: > >> Hola, >> >> Hola a todos, >> Os escribo porque no consigo finalizar el script necesario para realizar >> lo que a continuación planteo. Partiendo de un data frame (2 millones de >> casos), tengo: >> >> > datos2 >> ID FECHA YEAR CANTIDAD >> 1 100 2005-08-02 2005 1 >> 2 100 2005-10-19 2005 2 >> 3 100 2007-02-09 2007 1 >> 4 100 2007-10-25 2007 1 >> 5 100 2007-10-29 2007 1 >> 6 120 2006-05-11 2006 1 >> 7 120 2006-08-17 2006 5 >> 8 120 2006-10-15 2006 1 >> 9 120 2007-04-16 2007 3 >> >> Y desearía las cantidades acumuladas por ID y año, a partir del primer >> año con registros de cada ID, obteniendo: >> ID YEAR CANTIDAD >> 1 100 2005 3 >> 2 100 2006 3 (como en el 2006 no hay datos de ID=100, el >> acumulado se mantiene) >> 3 100 2007 6 >> 4 120 2006 7 >> 5 120 2007 10 >> >> Hasta ahora sólo he conseguido llegar a esto mediante el paquete >> data.table: >> > library(data.table) >> > datos2 <- data.table(datos2) >> > datos2 <- datos2[, ACUM.CANTIDAD:=cumsum(CANTIDAD), by = list(ID, YEAR)] >> > datos2 >> ID FECHA YEAR CANTIDAD ACUM.CANTIDAD >> 1: 100 2005-08-02 2005 1 1 >> 2: 100 2005-10-19 2005 2 3 >> 3: 100 2007-02-09 2007 1 1 >> 4: 100 2007-10-25 2007 1 2 >> 5: 100 2007-10-29 2007 1 3 >> 6: 120 2006-05-11 2006 1 1 >> 7: 120 2006-08-17 2006 5 6 >> 8: 120 2006-10-15 2006 1 7 >> 9: 120 2007-04-16 2007 3 3 >> >> Cualquier ayuda será bienvenida. Muchísimas gracias. >> >> >> >> [[alternative HTML version deleted]] >> >> >> _______________________________________________ >> R-help-es mailing list >> R-help-es@r-project.org >> https://stat.ethz.ch/mailman/listinfo/r-help-es >> >> > > > -- > Saludos, > Carlos Ortega > www.qualityexcellence.es >-- Saludos, Carlos Ortega www.qualityexcellence.es [[alternative HTML version deleted]]