All-in on R⁶ : Progress [bars] on first post

@eddelbuettel’s idea is a good one. (it’s a quick read…jump there and come back). We’ll avoid confusion and call it R⁶ over here. Feel free to don the superclass.

I often wait for a complete example or new package announcement to blog something when a briefly explained snippet might have sufficient utility for many R users. Also, tweets are fleeting and twitter could end up on the island of misfit social media sites if it can’t generate revenue or find a giant buyer this year. Don’t get me wrong, twitter convos are fine/useful, but blogs are at least semi-permanent, especially if you let them be hoovered up by the Internet Archive (“Save Page Now” on their site or use this handy Chrome extension).

I’ll tag all R⁶ posts as “r6” if you want to auto-filter those out of your stream or just page through them.

I’ll also lead off the these micro-posts with a simple one: adding progress bars to your tidyverse purrr operations.

The purrr::map* functions enable expressive and type-safe vectorized operations. Mine are usually over a few million/billion IPv4 addresses or domain names/URLs and often involve moderately lengthy tasks so I usually add the ability to incorporate progress bars to functions I make (and, I’m trying hard to get out of the bad habit of long-ish anonymous functions in purrr calls). The following is a toy example, but it’s a working example you can run in your interactive R session now:


arduously_long_nchar <- function(input_var, .pb=NULL) {
  if ((!is.null(.pb)) && inherits(.pb, "Progress") && (.pb$i < .pb$n)) .pb$tick()$print()

pb <- progress_estimated(length(letters))

map_int(letters, arduously_long_nchar, .pb=pb)

And, yes, I did make you wait ~26 seconds (unless you were intrepid enough to reduce the amount of sleep time :-)

If you happen to forget the progress bar object (or know you don’t need one):

map_int(letters, arduously_long_nchar)

the function still works (sans progress bars).

If you happen to also mess up what you pass in to the .pb parameter or get your progress bar out of sync with your object it won’t error out on you (it can be made much safer and wrapped in another function, say — tick_off(.pb) — but this is supposed to be a small post).

Comments/feedback/your-own-progress-methods are most welcome and encouraged.

Cover image from Data-Driven Security
Amazon Author Page

6 Comments All-in on R⁶ : Progress [bars] on first post

  1. Pingback: All-in on R⁴ : Progress [bars] on first post – Mubashir Qasim

  2. Pingback: All-in on R⁴ : Progress [bars] on first post – Cyber Security

  3. Rafael H M Pereira

    Hi Bob, that’s a really nice and flexible way to create a progress bar but I’d like to pick your brain about progress bars. Do you see any obvious advantages of progress_estimated{dplyr} over pbapply ?

    I have been using the pbapply library to create progress bars. In your example it would be.

    pbsapply(letters, arduouslylongnchar), or
    pblapply(letters, arduouslylongnchar) depending on the desired output format.

    1. hrbrmstr

      I used to use pbapply functions all the time. purrr map functions have type-safety, really nice anon shorthand (~{} makes an anon function w/., .x, .y auto-vars), and I think map_df(…) with my progress bar is way better than a bind_rows() after a pblapply, especially with that type-safety thing I mentioned.

      It’d be possible to write a wrapper library that does the same thing for purrr functions, too. Ultimately, the idiom that works for you (i.e. enables you to Get Stuff Done™) is the most important thing.

  4. Rafael Zayas

    This is excellent, and i’m a big fan of short posts like this. Thanks!

    One question: Any thoughts about how to roll this into a progress bar class to rule them all, i.e. one so a function could work interactively, and then also with Shiny like so:

    (Yes, I was also compelled to comment to make this multiple Rafaels)


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.