studio statement multiple loop ifelse for else conditions r optimization while-loop nested multicore

statement - ¿Cómo optimizar el siguiente código con while-loop anidado? ¿Multicore una opción?



if else r studio (1)

Estoy teniendo un desafío con un código que lleva mucho tiempo ejecutar y me pregunto cuáles son los trucos clave para optimizar el tiempo de ejecución de este código. Tengo que admitir que el data.frame de entrada es significativo (140,000 filas) y que el data.frame de salida es de aproximadamente 220,000 filas.

Una muestra de la entrada data.frame:

head(extremes) X_BusinessIDDescription min max month ID105 2007-12-01 2008-06-01 2007-12-01 ID206 2007-12-01 2009-07-01 2007-12-01 ID204 2007-12-01 2008-02-01 2007-12-01 ID785 2008-07-01 2010-08-01 2008-07-01 ID125 2007-11-01 2008-07-01 2007-11-01 ID107 2007-11-01 2011-06-01 2007-11-01

El data.frame que se extenderá con el bucle. El data.frame se inicia para obtener la estructura en su lugar.

output <- extremes[1,] output X_BusinessIDDescription min max month ID105 2007-12-01 2008-06-01 2007-12-01

Otros valores

IDcounter <- 1 IDmax <- nrow(extremes) linecounter <- 1

El while-loop me gustaría optimizar:

while (IDcounter <= IDmax){ start <- extremes$min[IDcounter] end <- extremes$max[IDcounter] # add three months while(start <= end){ output[linecounter,] <- extremes[IDcounter,] output$month[linecounter] <- start linecounter <- linecounter+1 start <- seq(start, by ="month", length=2)[2] } IDcounter <- IDcounter + 1 }

Para un pequeño número de filas, este código se ejecuta bastante rápido, pero parece que se está desacelerando a medida que se extiende la salida.

El resultado se ve así:

head(output) X_BusinessIDDescription min max month ID105 2007-12-01 2008-06-01 2007-12-01 ID105 2007-12-01 2008-06-01 2008-01-01 ID105 2007-12-01 2008-06-01 2008-02-01 ID105 2007-12-01 2008-06-01 2008-03-01 ID105 2007-12-01 2008-06-01 2008-04-01 ID105 2007-12-01 2008-06-01 2008-05-01

Por cada mes en el intervalo entre min y max en el archivo extremo se crea una fila.

También me interesaría saber cómo puedo hacer para que este código pueda tener en cuenta los múltiples núcleos de recursos informáticos disponibles. De acuerdo, admito que esto no es realmente una optimización, pero reducirá el tiempo de ejecución, que también es importante.

Jochem


Como ya se mencionó en @CarlWitthoft, debe reconsiderar su estructura de datos debido a la cantidad de datos duplicados.

Aquí encontrará un enfoque vectorizado simple:

## create all possible ranges of months ranges <- mapply(function(mi, ma) {seq(from=mi, to=ma, by="month")}, mi=extremes$min, ma=extremes$max) ## how many months per ID? n <- unlist(lapply(ranges, length)) ## create new data.frame output <- data.frame(X_BusinessIDDescription=rep(extremes$X_BusinessIDDescription, n), min=rep(extremes$min, n), max=rep(extremes$max, n), month=as.Date(unlist(ranges), origin="1970-01-01"), stringsAsFactors=FALSE)

Comparación con su enfoque:

extremes <- data.frame(X_BusinessIDDescription=c("ID105", "ID206", "ID204", "ID785", "ID125", "ID107"), min=as.Date(c("2007-12-01", "2007-12-01", "2007-12-01", "2008-07-01", "2007-11-01", "2007-11-01")), max=as.Date(c("2008-06-01", "2009-07-01", "2008-02-01", "2010-08-01", "2008-07-01", "2011-06-01")), month=as.Date(c("2007-12-01", "2007-12-01", "2007-12-01", "2008-07-01", "2007-11-01", "2007-11-01")), stringsAsFactors=FALSE) approachWhile <- function(extremes) { output <- data.frame(X_BusinessIDDescription=NA, min=as.Date("1970-01-01"), max=as.Date("1970-01-01"), month=as.Date("1970-01-01"), stringsAsFactors=FALSE) IDcounter <- 1 IDmax <- nrow(extremes) linecounter <- 1 while (IDcounter <= IDmax){ start <- extremes$min[IDcounter] end <- extremes$max[IDcounter] # add three months while(start <= end){ output[linecounter,] <- extremes[IDcounter,] output$month[linecounter] <- start linecounter <- linecounter+1 start <- seq(start, by ="month", length=2)[2] } IDcounter <- IDcounter + 1 } return(output) } approachMapply <- function(extremes) { ranges <- mapply(function(mi, ma) {seq(from=mi, to=ma, by="month")}, mi=extremes$min, ma=extremes$max) n <- unlist(lapply(ranges, length)) output <- data.frame(X_BusinessIDDescription=rep(extremes$X_BusinessIDDescription, n), min=rep(extremes$min, n), max=rep(extremes$max, n), month=as.Date(unlist(ranges), origin="1970-01-01"), stringsAsFactors=FALSE) return(output) } identical(approachWhile(extremes), approachMapply(extremes)) ## TRUE library("rbenchmark") benchmark(approachWhile(extremes), approachMapply(extremes), order="relative") # test replications elapsed relative user.self sys.self #2 approachMapply(extremes) 100 0.176 1.00 0.172 0.000 #1 approachWhile(extremes) 100 6.102 34.67 6.077 0.008