Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

progressr 0.8.0 is on CRAN. It comes with some new features:

• A new ‘rstudio’ handler that reports on progress via the RStudio job interface in RStudio

• withProgressShiny() now updates the detail part, instead of the message part

• In addition to signalling relative amounts of progress, it’s now also possible to signal total amounts

If you’re curious what progressr is about, have a look at my e-Rum 2020 presentation.

## Progress updates in RStudio’s job interface

If you’re using RStudio Console, you can now report on progress in the RStudio’s job interface as long as the progress originates from a progressr-signalling function. I’ve shown an example of this in Figure 1.

To try this yourself, run the below in the RStudio Console.

library(progressr)
handlers(global = TRUE)
handlers("rstudio")
y <- slow_sum(1:10)


The progress bar disappears when the calculation completes.

## Tweaks to withProgressShiny()

The withProgressShiny() function, which is a progressr-aware version of withProgress(), gained argument inputs. It defaults to inputs = list(message = NULL, detail = "message"), which says that a progress message should update the ‘detail’ part of the Shiny progress panel. For example,

X <- 1:10
withProgressShiny(message = "Calculation in progress",
detail = "Starting ...",
value = 0, {
p <- progressor(along = X)
y <- lapply(X, FUN=function(x) {
Sys.sleep(0.25)
p(sprintf("x=%d", x))
})
})


will start out as in the left panel of Figure 2, and, as soon as the first progress signal is received, the ‘detail’ part is updated with x=1 as shown in the right panel.

Prior to this new release, the default behavior was to update the ‘message’ part of the Shiny progress panel. To revert to the old behavior, set argument inputs as in:

X <- 1:10
withProgressShiny(message = "Starting ...",
detail = "Calculation in progress",
value = 0, {
p <- progressor(along = X)
y <- lapply(X, FUN=function(x) {
Sys.sleep(0.25)
p(sprintf("x=%d", x))
})
}, inputs = list(message = "message", detail = NULL))


This results in what you see in Figure 3. I think that the new behavior, as shown in Figure 2, looks better and makes more sense.

## Update to a specific amount of total progress

When using progressr, we start out by creating a progressor function that we then call to signal progress. For example, if we do:

my_slow_fun <- function() {
p <- progressr::progressor(steps = 10)
count <- 0
for (i in 1:10) {
count <- count + 1
p(sprintf("count=%d", count))
}
count
})


each call to p() corresponds to p(amount = 1), which signals that our function have moved amount = 1 steps closer to the total amount steps = 10. We can take smaller or bigger steps by specifying another amount.

In this new version, I’ve introduced a new beta feature that allows us to signal progress that says where we are in absolute terms. With this, we can do things like:

my_slow_fun <- function() {
p <- progressr::progressor(steps = 10)
count <- 0
for (i in 1:5) {
count <- count + 1
if (runif(1) < 0.5) break
Sys.sleep(2)
p(sprintf("count=%d", count))
}
## In case we broke out of the loop early,
## make sure to update to 5/10 progress
p(step = 5)
for (i in 1:5) {
count <- count + 1
Sys.sleep(2)
p(sprintf("count=%d", count))
}
count
}


When calling my_slow_fun(), we might see progress being reported as:

- [------------------------------------------------]   0%
\ [===>-------------------------------------]  10% count=1
| [=======>---------------------------------]  20% count=2
\ [===================>---------------------]  50% count=3
...


Note how it took a leap from 20% to 50% when count == 2. If we run it another again, the move to 50% might happen at another iteration.

## Wrapping up

There are also a few bug fixes, which you can read about in NEWS. And a usual, all of this work also when you run in parallel using the future framework.

Make progress!