0

What I want to do is to make the output from the for loop run available for many render outputs in Shiny App. I created the simple example of my problem. There is the same for loop in each renderPrint() function. Can I code that in such a way that the for loop is moved outside render*() functions?

I've found examples how to use reactives in loops but haven't found a solution to the reversed task. Thank you for your help and attention.

    library(shiny)

   ui <- fluidPage(sidebarLayout(
      sidebarPanel(
        numericInput(
          inputId = "seed",
          label = "Set seed:",
          value = 1
        ),
       numericInput(
          inputId = "Number",
          label = "Number:",
          value = 1,
          min = 1,
          step = 1
        )
      ),
      mainPanel(
         verbatimTextOutput("summary"),
         dataTableOutput("table"),
         verbatimTextOutput("data")
      )
    ))


    server <- function(input, output) {
      a <- reactive({
        set.seed(input$seed)
        rnorm(input$Number, 2, 1)
      })

      b <- reactive({
        5 * a()
      })

     rn <- reactive({
       c(1:input$Number)
      })

      fun <- function(x, y) {
        x + y
      }

       Table <- reactive({
        data.frame(rn = rn(),
                   a = a(),
                   b = b())
      })


      output$table <- renderDataTable({
        Table()
       })
      output$summary <- renderPrint({
         for (i in Table()$rn) {
           print (fun(Table()$a[i], Table()$b[i]))
       }
        })


        output$data <- renderPrint({
         for (i in Table()$rn) {
           print (fun(Table()$a[i], Table()$b[i]))
         } 
       })
    }


     shinyApp(ui = ui, server = server)
Zofia
  • 25
  • 4

1 Answers1

1

Extract the for loop into a function. You can use reactive values in functions with no problem, as long as you're not calling the function outside a reactive context (render*, reactive, observe).

Example:

printTable <- function() {
  for (i in Table()$rn) {
    print (fun(Table()$a[i], Table()$b[i]))
  }
}

output$summary <- renderPrint({
  printTable()
})

output$data <- renderPrint({
  printTable()
})

or more efficiently, you could capture the print output as a string and just re-use it:

capturedTableString <- reactive({
  capture.output({
    for (i in Table()$rn) {
      print (fun(Table()$a[i], Table()$b[i]))
    }
  })
})

printTable <- function() {
  cat(capturedTableString(), sep = "\n")
}

output$summary <- renderPrint({
  printTable()
})
greg L
  • 4,034
  • 1
  • 19
  • 18