{"id":14068702,"url":"https://github.com/psolymos/pbapply","last_synced_at":"2025-04-07T15:05:25.001Z","repository":{"id":22167665,"uuid":"25499363","full_name":"psolymos/pbapply","owner":"psolymos","description":"Adding progress bar to '*apply' functions in R","archived":false,"fork":false,"pushed_at":"2024-09-21T19:20:41.000Z","size":19269,"stargazers_count":158,"open_issues_count":3,"forks_count":6,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-31T14:09:14.196Z","etag":null,"topics":["cran","progress-bar","r","r-package","rstats","rstats-package"],"latest_commit_sha":null,"homepage":"https://peter.solymos.org/pbapply/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/psolymos.png","metadata":{"files":{"readme":"README.md","changelog":"NEWS.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-10-21T03:10:20.000Z","updated_at":"2025-02-25T22:12:50.000Z","dependencies_parsed_at":"2023-01-14T13:15:07.357Z","dependency_job_id":"58ee7f3b-7300-4c4b-9306-bde6f7eca6f8","html_url":"https://github.com/psolymos/pbapply","commit_stats":{"total_commits":1415,"total_committers":8,"mean_commits":176.875,"dds":"0.24805653710247355","last_synced_commit":"307f33372c19adceeb1ed9aded1bfdf1e1ba98df"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fpbapply","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fpbapply/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fpbapply/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psolymos%2Fpbapply/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/psolymos","download_url":"https://codeload.github.com/psolymos/pbapply/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247675597,"owners_count":20977376,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cran","progress-bar","r","r-package","rstats","rstats-package"],"created_at":"2024-08-13T07:06:21.353Z","updated_at":"2025-04-07T15:05:24.976Z","avatar_url":"https://github.com/psolymos.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"# pbapply: adding progress bar to '*apply' functions in R\n\n[![CRAN version](https://www.r-pkg.org/badges/version/pbapply)](https://CRAN.R-project.org/package=pbapply)\n[![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/grand-total/pbapply)](https://www.rdocumentation.org/packages/pbapply/)\n[![check](https://github.com/psolymos/pbapply/actions/workflows/check.yml/badge.svg)](https://github.com/psolymos/pbapply/actions/workflows/check.yml)\n\nA lightweight package that adds progress bar to vectorized R functions\n(`*apply`). The implementation can easily be added to functions where showing the progress is\nuseful (e.g. bootstrap). The type and style of the progress bar (with percentages or remaining time) can be set through options.\nThe package supports several [parallel processing backends](#parallel-backends), such as snow-type clusters, multicore-type forking, and future.\n\n![](https://github.com/psolymos/pbapply/raw/master/images/pbapply-02.gif)\n\n- [pbapply: adding progress bar to '\\*apply' functions in R](#pbapply-adding-progress-bar-to-apply-functions-in-r)\n  - [Versions](#versions)\n  - [How to get started?](#how-to-get-started)\n      - [1. You are not yet an R user](#1-you-are-not-yet-an-r-user)\n      - [2. You are an R user but haven't used vectorized functions yet](#2-you-are-an-r-user-but-havent-used-vectorized-functions-yet)\n      - [3. You are an R user familiar with vectorized functions](#3-you-are-an-r-user-familiar-with-vectorized-functions)\n      - [4. You are a seasoned R developer writing your own packages](#4-you-are-a-seasoned-r-developer-writing-your-own-packages)\n  - [How to add pbapply to a package](#how-to-add-pbapply-to-a-package)\n      - [1. Suggests: pbapply](#1-suggests-pbapply)\n      - [2. Depends/Imports: pbapply](#2-dependsimports-pbapply)\n      - [Customizing the progress bar in your package](#customizing-the-progress-bar-in-your-package)\n      - [Suppressing the progress bar in your functions](#suppressing-the-progress-bar-in-your-functions)\n      - [Working with a future backend](#working-with-a-future-backend)\n  - [Examples](#examples)\n      - [Command line usage](#command-line-usage)\n      - [Parallel backends](#parallel-backends)\n      - [Progress with Shiny](#progress-with-shiny)\n\n## Versions\n\nInstall CRAN release version (recommended):\n\n```R\ninstall.packages(\"pbapply\")\n```\n\nDevelopment version:\n\n```R\ninstall.packages(\"pbapply\", repos = \"https://psolymos.r-universe.dev\")\n```\n\nSee user-visible changes in the [NEWS](https://github.com/psolymos/pbapply/blob/master/NEWS.md) file.\n\nUse the [issue tracker](https://github.com/psolymos/pbapply/issues)\nto report a problem, or to suggest a new feature.\n\n## How to get started?\n\n#### 1. You are not yet an R user\n\nIn this case, start with understanding basic programming concepts,\nsuch as data structures (matrices, data frames, indexing these),\n`for` loops and functions in R.\nThe online version of Garrett Grolemund's\n[_Hands-On Programming with R_](https://rstudio-education.github.io/hopr/) \nwalks you through these concepts nicely.\n\n#### 2. You are an R user but haven't used vectorized functions yet\n\nLearn about vectorized functions designed to replace `for` loops:\n`lapply`, `sapply`, and `apply`.\nHere is a repository called \n[_The Road to Progress_](https://github.com/psolymos/the-road-to-progress) \nthat I created to show you how to go from a `for` loop to `lapply`/`sapply`.\n\n\u003ca href=\"https://www.youtube.com/watch?feature=player_embedded\u0026v=uyhIiTTrTJY\" target=\"_blank\"\u003e\n \u003cimg src=\"https://img.youtube.com/vi/uyhIiTTrTJY/mqdefault.jpg\" alt=\"Watch the video\" width=\"240\" height=\"180\" border=\"0\" /\u003e\n\u003c/a\u003e\n\n#### 3. You are an R user familiar with vectorized functions\n\nIn this case, you can simply add `pbapply::pb` before your `*apply`\nfunctions, e.g. `apply()` will become `pbapply::pbapply()`, etc.\nYou can guess what happens.\nNow if you want to speed things up a little (or a lot),\ntry `pbapply::pbapply(..., cl = 4)` to use 4 cores instead of 1.\n\nIf you are a Windows user, things get a bit more complicated, but not much.\nCheck how to work with `parallel::parLapply` to set up a snow type cluster\nor use a suitable future backend (see some examples [below](#parallel-backends)).\nHave a look at the \n[_The Road to Progress_](https://github.com/psolymos/the-road-to-progress) \nrepository to see more worked examples.\n\n#### 4. You are a seasoned R developer writing your own packages\n\nRead on, the next section is for you.\n\n## How to add pbapply to a package\n\nThere are two ways of adding the pbapply package to another package.\n\n#### 1. Suggests: pbapply\n\nAdd pbapply to the `Suggests` field in the `DESCRIPTION`.\n\nUse a conditional statement in your code to fall back on a base function in case of pbapply is not installed:\n\n```R\nout \u003c- if (requireNamespace(\"pbapply\", quietly = TRUE)) {\n   pbapply::pblapply(X, FUN, ...)\n} else {\n   lapply(X, FUN, ...)\n}\n```\n\nSee a small example package [here](https://github.com/psolymos/pbapplySuggests).\n\n#### 2. Depends/Imports: pbapply\n\nAdd pbapply to the `Depends` or `Imports` field in the `DESCRIPTION`.\n\nUse the pbapply functions either as `pbapply::pblapply()` or specify them in the `NAMESPACE` (`importFrom(pbapply, pblapply)`) and\nuse it as `pblapply()` (without the `::`). \nYou'd have to add a comment `#' @importFrom pbapply pblapply` if you are [using roxygen2](https://roxygen2.r-lib.org/articles/namespace.html#imports).\n\n#### Customizing the progress bar in your package\n\nSpecify the progress bar options in the `zzz.R` file of the package:\n\n```R\n.onAttach \u003c- function(libname, pkgname){\n    options(\"pboptions\" = list(\n        type = if (interactive()) \"timer\" else \"none\",\n        char = \"-\",\n        txt.width = 50,\n        gui.width = 300,\n        style = 3,\n        initial = 0,\n        title = \"R progress bar\",\n        label = \"\",\n        nout = 100L,\n        min_time = 2))\n    invisible(NULL)\n}\n```\n\nThis will set the options and pbapply will not override these when loaded.\n\nSee a small example package [here](https://github.com/psolymos/pbapplyDepends).\n\n#### Suppressing the progress bar in your functions\n\nSuppressing the progress bar is sometimes handy. By default, progress bar is suppressed when `!interactive()`.\nIn other instances, put this inside a function:\n\n```R\npbo \u003c- pboptions(type = \"none\")\non.exit(pboptions(pbo), add = TRUE)\n```\n\n#### Working with a future backend\n\nThe future backend might require additional arguments to be set by package developers to avoid warnings for end users.\nMost notably, you will have to determine how to handle random number generation as part of parallel evaluation.\nYou can pass the `future.seed` argument directly through `...`.\nIn general, ass any additional arguments to `FUN` immediately following the `FUN` argument, \nand any additional arguments to the the future backend after `cl = \"future\"` statement:\n\n```R\npblapply(1:2, FUN = my_fcn, {additional my_fcn args}, cl = \"future\", {additional future args})\n```\n\nSee [this issue](https://github.com/psolymos/pbapply/issues/60) for a discussion.\n\n## Examples\n\nThe following `pb*` functions are available in the pbapply package:\n\n| base         | pbapply         | works in parallel |\n|--------------|-----------------|-------------------|\n|  `apply`     |  `pbapply`      |  ✅               |\n|  `by`        |  `pbby`         |  ✅               |\n|  `eapply`    |  `pbeapply`     |  ✅               |\n|  `lapply`    |  `pblapply`     |  ✅               |\n|  `.mapply`   |  `pb.mapply`    |  ❌               |\n|  `mapply`    |  `pbmapply`     |  ❌               |\n|  `Map`       |  `pbMap`        |  ❌               |\n|  `replicate` |  `pbreplicate`  |  ✅               |\n|  `sapply`    |  `pbsapply`     |  ✅               |\n|  `tapply`    |  `pbtapply`     |  ✅               |\n|  `vapply`    |  `pbvapply`     |  ✅               |\n|  ❌          |  `pbwalk`       |  ✅               |\n\n#### Command line usage\n\n```R\nlibrary(pbapply)\nset.seed(1234)\nn \u003c- 2000\nx \u003c- rnorm(n)\ny \u003c- rnorm(n, model.matrix(~x) %*% c(0,1), sd=0.5)\nd \u003c- data.frame(y, x)\n## model fitting and bootstrap\nmod \u003c- lm(y~x, d)\nndat \u003c- model.frame(mod)\nB \u003c- 500\nbid \u003c- sapply(1:B, function(i) sample(nrow(ndat), nrow(ndat), TRUE))\nfun \u003c- function(z) {\n    if (missing(z))\n        z \u003c- sample(nrow(ndat), nrow(ndat), TRUE)\n    coef(lm(mod$call$formula, data=ndat[z,]))\n}\n\n## standard '*apply' functions\n# system.time(res1 \u003c- lapply(1:B, function(i) fun(bid[,i])))\n#    user  system elapsed\n#   1.096   0.023   1.127\nsystem.time(res2 \u003c- sapply(1:B, function(i) fun(bid[,i])))\n#    user  system elapsed\n#   1.152   0.017   1.182\nsystem.time(res3 \u003c- apply(bid, 2, fun))\n#    user  system elapsed\n#   1.134   0.010   1.160\nsystem.time(res4 \u003c- replicate(B, fun()))\n#    user  system elapsed\n#   1.141   0.022   1.171\n\n## 'pb*apply' functions\n## try different settings:\n## \"none\", \"txt\", \"tk\", \"win\", \"timer\"\nop \u003c- pboptions(type=\"timer\") # default\nsystem.time(res1pb \u003c- pblapply(1:B, function(i) fun(bid[,i])))\n#    |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% ~00s\n#    user  system elapsed\n#   1.539   0.046   1.599\npboptions(op)\n\npboptions(type=\"txt\")\nsystem.time(res2pb \u003c- pbsapply(1:B, function(i) fun(bid[,i])))\n#   |++++++++++++++++++++++++++++++++++++++++++++++++++| 100%\n#    user  system elapsed\n#   1.433   0.045   1.518\npboptions(op)\n\npboptions(type=\"txt\", style=1, char=\"=\")\nsystem.time(res3pb \u003c- pbapply(bid, 2, fun))\n# ==================================================\n#    user  system elapsed\n#   1.389   0.032   1.464\npboptions(op)\n\npboptions(type=\"txt\", char=\":\")\nsystem.time(res4pb \u003c- pbreplicate(B, fun()))\n#   |::::::::::::::::::::::::::::::::::::::::::::::::::| 100%\n#    user  system elapsed\n#   1.427   0.040   1.481\npboptions(op)\n```\n\n#### Parallel backends\n\nYou have a few different options to choose from as a backend. This all comes down to the `cl` argument in the `pb*` functions.\n\n- `cl = NULL` (default): sequential execution\n- `cl` is of class cluster: this implies that you used `cl = parallel::makeCluster(n)` or something similar (`n` being the number of worker nodes)\n- `cl` is a positive integer (usually \u003e 1): forking type parallelism is used in this case\n- `cl = \"future\"`: you are using one of the [future](https://CRAN.R-project.org/package=future) plans and parallelism is defined outside of the `pb*` call.\n\nNote that on Windows the forking type is not available and `pb*` functions will fall back to sequential evaluation.\n\nSome examples:\n\n```R\nf \u003c- function(i) Sys.sleep(1)\n\n## sequential\npblapply(1:2, f)\n\n## cluster\ncl \u003c- parallel::makeCluster(2)\npblapply(1:2, f, cl = cl)\nparallel::stopCluster(cl)\n\n## forking\npblapply(1:2, f, cl = 2)\n\n## future\nlibrary(future)\n\ncl \u003c- parallel::makeCluster(2)\nplan(cluster, workers = cl)\nr2 \u003c- pblapply(1:2, f, cl = \"future\")\nparallel::stopCluster(cl)\n\nplan(multisession, workers = 2)\npblapply(1:2, f, cl = \"future\")\n\nplan(sequential)\n```\n\n#### Progress with Shiny\n\n```R\nlibrary(shiny)\nlibrary(pbapply)\n\npboptions(\n    type = \"shiny\",\n    title = \"Shiny progress\",\n    label = \"Almost there ...\")\n\nui \u003c- fluidPage(\n    plotOutput(\"plot\")\n)\n\nserver \u003c- function(input, output, session) {\n    output$plot \u003c- renderPlot({\n        pbsapply(1:15, function(z) Sys.sleep(0.5))\n        plot(cars)\n    })\n}\n\nshinyApp(ui, server)\n```\n\n![](https://github.com/psolymos/pbapply/raw/master/images/shiny.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpsolymos%2Fpbapply","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpsolymos%2Fpbapply","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpsolymos%2Fpbapply/lists"}