Adding progress bar to functions that do not imply iterations

Hi,
I would like to know whether there's way to add a progress bar to a general function with does not imply iterating over multiple elements .

I had a look at the package progressr which provides tools to add a progress bar but I couldn't find any examples on functions that do not require iterations.

E.g. adding a progress bar to the join_progress funcion hereunder

Thank you for your help

library(sf)
#> Linking to GEOS 3.10.2, GDAL 3.3.2, PROJ 7.2.1; sf_use_s2() is TRUE
#> WARNING: different compile-time and runtime versions for GEOS found:
#> Linked against: 3.10.2-CAPI-1.16.0 compiled against: 3.9.1-CAPI-1.14.2
#> It is probably a good idea to reinstall sf, and maybe rgeos and rgdal too
library(raster)
#> Loading required package: sp
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:raster':
#> 
#>     intersect, select, union
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(spData)
#> To access larger datasets in this package, install the spDataLarge
#> package with: `install.packages('spDataLarge',
#> repos='https://nowosad.github.io/drat/', type='source')`
library(progressr)

#  enable the global progress handler

handlers(global = TRUE)
#> Error in globalCallingHandlers(condition = global_progression_handler): should not be called with handlers on the stack



set.seed(2018) # set seed for reproducibility
(bb_world = st_bbox(world)) # the world's bounds
#>       xmin       ymin       xmax       ymax 
#> -180.00000  -89.90000  179.99999   83.64513
#>   xmin   ymin   xmax   ymax 
#> -180.0  -89.9  180.0   83.6
random_df = tibble(
  x = runif(n = 10, min = bb_world[1], max = bb_world[3]),
  y = runif(n = 10, min = bb_world[2], max = bb_world[4])
)
random_points = random_df %>% 
  st_as_sf(coords = c("x", "y")) %>% # set coordinates
  st_set_crs(4326) # set geographic CRS

world_random = world[random_points, ]



join_progress<-function(x) {
  
  Sys.sleep(10)
  st_join(x, world["name_long"])
  
}


random_joined = join_progress(random_points)

Short answer: not possible to do what you want.

Longer answer, it's easy to do what you ask: the iteration is not necessary, you could add calls to a progressor between other function calls:

library(progressr)


my_function_without_iteration <- function(){
  p <- progressr::progressor(steps = 5)
  
  # First long operation
  Sys.sleep(.2)
  p()
  # Second long operation
  Sys.sleep(.2)
  p()
  # Third long operation
  Sys.sleep(.2)
  p()
  # Fourth long operation
  Sys.sleep(.2)
  p()
  # Fifth long operation
  Sys.sleep(.2)
  
}

with_progress(my_function_without_iteration())

Created on 2023-12-15 with reprex v2.0.2

However to do that you still need to insert the calls to p() inside the computation. In your example code, there are two long steps Sys.sleep(10) and st_join(x, world["name_long"]), and you have no idea how long they will take to process (well, you do in the case of Sys.sleep but you wouldn't for a real computation). How would a progressor know when to display progress?

This only works if you have access to the inside of the function. So unless the developers who wrote st_join() included code to manage the progress bar, you can't just slap it on top.

Thank you,
so I should call p after every step like this


join_progress<-function(x) {
  p<-progressr::progressor(step=2)
  Sys.sleep(10)
  p()
  st_join(x, world["name_long"])
  p()
}


random_joined = with_progress(join_progress(random_points))

Yes, that would give you a bar that progresses twice, 50% after the Sys.sleep(), and 100% after the st_join().

This topic was automatically closed 42 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.