Sebastian Zeki
Sebastian Zeki

Reputation: 6874

Progress bar for a function within a function in Shiny

I have a function from a package that runs a series of other functions within it. I would love to show each of those functions as a separate Progressbar as they are run. Is this possible?

I have used withProgress but this only shows the 'outer' function and doesn't show me the progress of the functions that run within it.

Upvotes: 0

Views: 1698

Answers (1)

user5029763
user5029763

Reputation: 1933

Welcome to SO, next time try to provide a minimal example. I'm using the 'Progress indicator' article provided by Rstudio as a base to answer you.

If I understood correctly, you are having trouble using withProgress with nested functions. You can use withProgress inside these functions:

library(shiny)

fun2 <- function(i,n,dat) {
  dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
  incProgress(1/n, detail = paste("Doing part", i))
  Sys.sleep(0.1)
  return(dat)
}

fun1 <- function(n) {
  dat <- data.frame(x = numeric(0), y = numeric(0))
  for (i in 1:n) { dat <- fun2(i,n,dat) }
  return(dat)
}

server <- function(input, output) {
  output$plot <- renderPlot({
    input$goPlot # Re-run when button is clicked
    withProgress(message = 'Making plot', value = 0, {
      n <- 10
      dat <- fun1(n)
    })
    plot(dat$x, dat$y)
  })
}

ui <- shinyUI(basicPage(
  plotOutput('plot', width = "300px", height = "300px"),
  actionButton('goPlot', 'Go plot')
))

shinyApp(ui = ui, server = server)

Another solution would be using global variables (just remember to be careful when using global variables).

library(shiny)
nprogress <- 10
iprogress <- 0

fun2 <- function(dat) {
  dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
  incProgress(1/nprogress, detail = paste("Doing part", iprogress))
  Sys.sleep(0.1)
  return(dat)
}

fun1 <- function(n) {
  dat <- data.frame(x = numeric(0), y = numeric(0))
  for (i in 1:n) {
    iprogress <<- i
    dat <- fun2(dat)
  }
  return(dat)
}

server <- function(input, output) {
  output$plot <- renderPlot({
    input$goPlot # Re-run when button is clicked
    withProgress(message = 'Making plot', value = 0, {
      n <- 10
      nprogress <<- n
      dat <- fun1(n)
    })
    plot(dat$x, dat$y)
  })
}

ui <- shinyUI(basicPage(
  plotOutput('plot', width = "300px", height = "300px"),
  actionButton('goPlot', 'Go plot')
))

shinyApp(ui = ui, server = server)

Upvotes: 3

Related Questions