Barra de progreso en R
Cuando se ejecutan estudios de simulación que tardan mucho en acabar, es muy útil añadir una barra de progreso para verificar el porcentaje completado de las iteraciones. En este tutorial aprenderás a agregar una barra de progreso en R mediante diferentes métodos, para verificar el progreso de los bucles for y de las funciones de la familia apply.
Insertar barra de progreso
La función txtProgressBar
Las funciones usadas de forma más habitual para crear barras de progreso son las funciones txtProgressBar
y setTxtProgressBar
de R base.
En el siguiente bloque de código mostramos cómo agregar una barra de progreso a un bucle for, describiendo brevemente los argumentos que puedes personalizar.
n_iter <- 50 # Número de iteraciones del bucle
# Inicializa la barra de progreso
pb <- txtProgressBar(min = 0, # Valor mínimo de la barra de progreso
max = n_iter, # Valor máximo de la barra de progreso
style = 3, # Estilo de la barra (también style = 1 y style = 2)
width = 50, # Ancho de la barra. Por defecto: getOption("width")
char = "=") # Carácter usado para crear la barra
for(i in 1:n_iter) {
#-------------------
# Aquí va tu código:
#-------------------
Sys.sleep(0.1) # Borra esta línea y añade tu código
#-------------------
# Actualiza la barra de progreso al estado actual
setTxtProgressBar(pb, i)
}
close(pb) # Cerramos la conexión
|==================================================| 100%>
A modo ilustrativo, para que el bucle tarde unos segundos en finalizar y se vea el avance de la barra de progreso en el ejemplo anterior se utiliza la función Sys.sleep
, que para la ejecución del código tantos segundos como se pasen como parámetro.
Tiempo transcurrido y restante estimado
Sin embargo, la función solo muestra el porcentaje actual de iteraciones que se han ejecutado.
De esta forma, con el objetivo de proporcionar mayor funcionalidad, hemos desarrollado una manera de mostrar el tiempo transcurrido y una estimación del tiempo restante estimado, basado en la media del tiempo que tomaron las iteraciones previas en ejecutarse. Ten en cuenta que para mostrar horas, minutos y segundos se utiliza la función seconds_to_perior
del paquete lubridate
.
# install.packages("lubridate")
library(lubridate)
n_iter <- 20
pb <- txtProgressBar(min = 0,
max = n_iter,
style = 3,
width = n_iter, # Necesario para evitar múltiples prints
char = "=")
inicio <- numeric(n_iter)
fin <- numeric(n_iter)
for(i in 1:n_iter){
inicio[i] <- Sys.time()
#-------------------
# Aquí va tu código:
#-------------------
Sys.sleep(0.1) # Borra esta línea y añade tu código
#-------------------
fin[i] <- Sys.time()
setTxtProgressBar(pb, i)
tiempo <- round(seconds_to_period(sum(fin - inicio)), 0)
# Tiempo restante estimado basado en el tiempo
# medio que tardaron en ejecutarse las iteraciones previas
est <- n_iter * (mean(fin[fin != 0] - inicio[inicio != 0])) - tiempo
restante <- round(seconds_to_period(est), 0)
cat(paste(" // Tiempo ejecución:", tiempo,
" // Tiempo restante estimado:", restante), "")
}
close(pb)
|====================| 100% // Tiempo ejecución: 2S // Tiempo restante estimado: 0S >
Si los valores especificados en los argumentos max
y width
son menores que el número de iteraciones, la función cat
imprimirá los valores múltiples veces.
El paquete progress
Como alternativa a las funciones anteriores puedes usar el paquete progress
, que permite mayor flexibilidad en la configuración de la salida.
Existen varios argumentos que puedes personalizar, así que recuerda escribir ?progress
para obtener detalles adicionales, pero el más relevante de ellos es el argumento format
, que permite modificar el formato de la barra de progreso como se quiera, mediante diferentes tipos de configuraciones.
En el siguiente bloque de código se muestra un ejemplo completo, con un spinner, la barra, el porcentaje completado, el tiempo transcurrido y el tiempo restante estimado:
# install.packages("progress")
library(progress)
n_iter <- 100
pb <- progress_bar$new(format = "(:spin) [:bar] :percent [Tiempo transcurrido: :elapsedfull || Tiempo restante estimado: :eta]",
total = n_iter,
complete = "=", # Caracteres de las iteraciones finalizadas
incomplete = "-", # Caracteres de las iteraciones no finalizadas
current = ">", # Carácter actual
clear = FALSE, # Si TRUE, borra la barra cuando termine
width = 100) # Ancho de la barra de progreso
for(i in 1:n_iter) {
# Actualiza el estado actual
pb$tick()
#-------------------
# Aquí va tu código:
#-------------------
Sys.sleep(0.1) # Borra esta línea y añade tu código
#-------------------
}
(|) [=========>---] 85% [Tiempo transcurrido: 00:00:08 || Tiempo restante estimado: 2s]
Barra de progreso de Windows con la función winProgressBar
Las barras de progreso descritas en las secciones anteriores estaban hechas con caracteres que se imprimían en la consola. Sin embargo, si lo prefieres, también es posible crear barras de progreso con una ventana estilo Windows con la funciones winProgressBar
y setWinProgressBar
.
El proceso para agregar la barra de progreso es análogo a los ejemplos anteriores, pero en este caso también puedes agregar un título y una descripción con los argumentos title
y label
, respectivamente. Ten en cuenta que si especificas una descripción o un título en la funciónsetWinProgressBar
, sobreescribirá los argumentos correspondientes establecidos en la función winProgressBar
.
n_iter <- 50 # Número de iteraciones
pb <- winProgressBar(title = "Barra de progreso de Windows", # Título de la ventana
label = "Porcentaje completado", # Texto de la ventana
min = 0, # Valor mínimo de la barra
max = n_iter, # Valor máximo de la barra
initial = 0, # Valor inicial de la barra
width = 300L) # Ancho de la ventana
for(i in 1:n_iter) {
#-------------------
# Aquí va tu código:
#-------------------
Sys.sleep(0.1) # Borra esta línea y añade tu código
#-------------------
pctg <- paste(round(i/n_iter *100, 0), "% completado")
setWinProgressBar(pb, i, label = pctg) # Al pasar pctg al argumento label se sobreescribirá
# el texto del argumento label de la función winProgressBar
}
close(pb) # Cerramos la conexión
Barra de progreso Tk (Unix) con la función tkProgressBar
La función descrita en la subsección anterior solo funcionará para sistemas Windows. Sin embargo, las funciones tkProgressBar
y setTkProgressBar
del paquete tcltk
te permitirán crear una barra de progreso Tk en plataformas Unix, como Linux:
# install.packages("tcltk")
library(tcltk)
n_iter <- 50 # Número de iteraciones
pb <- tkProgressBar(title = "Barra de progreso Tk", # Título de la ventana
label = "Porcentaje completado", # Texto de la ventana
min = 0, # Valor mínimo de la barra
max = n_iter, # Valor máximo de la barra
initial = 0, # Valor inicial de la barra
width = 300) # Ancho de la ventana
for(i in 1:n_iter) {
#-------------------
# Aquí va tu código:
#-------------------
Sys.sleep(0.1) # Borra esta línea y añade tu código
#-------------------
pctg <- paste(round(i/n_iter *100, 0), "% completado")
setTkProgressBar(pb, i, label = pctg)
}
close(pb) # Cerramos la conexión
Barra de progreso con funciones apply: el paquete pbapply
En la sección anterior revisamos cómo añadir barras de progreso a bucles for, por lo que en esta sección discutiremos cómo usar el paquete pbapply
, para añadir barras de progreso a las funciones de la familia apply.
El paquete proporciona las funciones pbapply
, pblapply
, pbsapply
, pbtapply
, pbmapply
y pbreplicate
. En el siguiente bloque de código mostramos un ejemplo usando la función pblapply
, pero todas las funciones proporcionan la misma funcionalidad.
# install.packages("pbapply")
library(pbapply)
pblapply(1:3, function(i){
Sys.sleep(1) # Sustituye estas líneas
i ^ 3 # por tu código
})
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=03s
[[1]]
[1] 1
[[2]]
[1] 8
[[3]]
[1] 27
Además, puedes personalizar el tipo de barra de progreso que se muestra con el argumento type
de la función pboptions
. Los posibles valores son "timer"
(por defecto), que muestra una barra de progreso con el tiempo restante estimado y el transcurrido, "txt"
, que elimina los tiempos, "win"
, que establece una barra de progreso de Windows, "tk"
para una barra estilo TK y "none"
, para no mostrar ninguna barra.
# Guardamos las opciones actuales
op <- pboptions()
# Establecemos un nuevo tipo de barra
pboptions(type = "win")
pbsapply(1:3, Sys.sleep) # Sustituye Sys.sleep por la función que quieras
# Volvemos a las opciones por defecto
pboptions(op)
Existen varios argumentos que puedes personalizar. Como ejemplo, puedes cambiar el carácter usado para crear la barra de progreso con el argumento char
, pero escribe ?pboptions
para obtener argumentos y detalles adicionales.
# Volvemos a las opciones por defecto,
# modificando el carácter de la barra
op <- pboptions(type = "timer", char = "=")
Paquete beepr: notificaciones de sonido cuando la ejecución finaliza
Por último, a pesar de que no proporciona una barra de progreso, el paquete beepr
package permite reproducir una notificación de audio con la función beep
, lo que puede ser muy útil cuando ejecutas un estudio de simulación que tarda mucho en finalizar y lo dejas de fondo. Por tanto, cuando la ejecución termine, un sonido te notificará. A continuación se muestra un ejemplo junto con una barra de progreso.
# install.packages("beepr")
library(beepr)
n_iter <- 100
pb <- txtProgressBar(style = 3)
for(i in 1:n_iter) {
#-------------------
# Aquí va tu código:
#-------------------
Sys.sleep(0.1) # Borra esta línea y añade tu código
#-------------------
setTxtProgressBar(pb, i)
}
beep(0) # Notificación aleatoria
close(pb) # Cerramos la conexión
Ten en cuenta que beep(0)
ejecuta un sonido al azar entre los disponibles, pero también puedes especificar un número entre 1 y 10 o establecer "ping"
, "coin"
, "fanfare"
, "complete"
, "treasure"
, "ready"
, "shotgun"
, "mario"
, "wilhelm"
o "facebook"
, respectivamente.