1

I am working on building a shiny App. I have used some filters and rendered a data frame and the data frame changes dynamically as per the user input. But I cannot store a particular column value from a data frame into a vector. I need to store the reactive output every time into a vector so that I can use the values later again. Here the values are stored in text_vec and i need to pass that into the API but I cannot access the values from text_vec and i have to pass the updated values every time into the API

library(dplyr)
library(shiny)

shinyApp(ui = fluidPage(

  sidebarLayout(

    sidebarPanel(
      selectInput(inputId = "cyl",
                  label = "Number cylinders:",
                  choices = c("all",sort(unique(mtcars$cyl))),
                  selected = "all"),
      actionButton("capture",
                   "capture value")

    ), # closes sidebarPanel


    mainPanel(

      tableOutput("text"),
      tableOutput("text2"),
      tableOutput("text3"),
      tableOutput("table")

    ) # closes mainPanel
  ) # closes sidebarLayout    

), # closes fluidPage

server = function(input, output) {

  # some example reactive data    
  cars_react <- reactive({

    mtcars %>% 
      filter(cyl == input$cyl | input$cyl == "all")

  })

  # simply global assignment of a reactive vector
  observeEvent(cars_react(), {

    # here is a globally assigned vector taken from the reactive data
    # reused in a render statement it will not react to change, since it is not reactive 

    test_vec3 <<- unique(cars_react()$hp)

  })



  # here a file is written to the working directory of your shiny app
  # everytime cars_react() changes write (and overwrite) vector to a file 
  observeEvent(cars_react(), {

    test_vec = unique(cars_react()$hp)

    saveRDS(test_vec, file = "test_vec.Rdata")

  })

  # same as above but the file is gradually growing and not overwritten
  # everytime cars_react() changes add vector to a (over several sessions growing) list
  observeEvent(cars_react(), {

    test_vec2 = unique(cars_react()$hp)

    if (file.exists("test_list.Rdata")) {

      temp = readRDS("test_list.Rdata")

      test_list = c(temp, list(test_vec2))

    } else {

      test_list = list(test_vec2)

    }

    saveRDS(test_list, file = "test_list.Rdata")


  })

  # here we access the reactive data with isolate and make it non-reactive, but can update the values through a button click
  text_vec <<- eventReactive(input$capture, {

    isolate(unique(cars_react()$hp))

  })



  # output of our reactive data as table
  output$table <- renderTable({

    cars_react()

  })   

  # text output of globally assigned non-reactive vector test_vec3 (not changing!)
  output$text <- renderText({

    test_vec3

  })   

  # you can capture values of reactives with isolate, but then, they don't change anymore 
  # text output of isolated formely reactive vector unique(cars_react()$hp (not changing!)
  output$text2 <- renderText({

    isolate(unique(cars_react()$hp))

  })   

  # text output of new reactive vector (changes when input$capture button is clicked)
  output$text3 <- renderText({
    text_vec()

  })  

  for (i in text_vec)
  {
    url = "https://oscar.com/prweb/PRRestService/"
    parameters<-'{
    {
    "Reference":"Account"
    ,"ReferenceValue":""
    }'
      b<-fromJSON(parameters)
      b["ReferenceValue"]=i
      r <- POST(url, body = parameters,encode = "json")
      r_c<-toJSON(content(r))
      print(r_c)
    }


  }


)
Rohit
  • 27
  • 2
  • It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. – MrFlick Oct 16 '19 at 20:12

2 Answers2

0

A simple way to get a data frame to persist across all environments used within your Shiny app, is to use the '<<-' assignment instead of the '<-" assignment. This is not a great programming technique, but it may be what you're hoping to find.

# To get a data frame to persist, use
a <<- b

# instead of
a <- b
S Novogoratz
  • 368
  • 2
  • 13
0

** Updated answer **

Based on your updated answer, I would wrap you API call into an observeEvent which gets triggered once the action button is pressed. Since you do not provide a working example with some real code, I am not sure whether the example below is of help. I further assume that your for loop is correct and working (on my end, I cannot know without a real API and some real values).

library(dplyr)
library(shiny)
library(httr)
library(jsonlite)

shinyApp(ui = fluidPage(


      selectInput(inputId = "cyl",
                  label = "Number cylinders:",
                  choices = c("all",sort(unique(mtcars$cyl))),
                  selected = "all"),
      actionButton("capture",
                   "capture value")


), # closes fluidPage

server = function(input, output) {

  # some example reactive data    
  cars_react <- reactive({

    mtcars %>% 
      filter(cyl == input$cyl | input$cyl == "all")

  })



  # here we access the reactive data with isolate and make it non-reactive, but can update the values through a button click
  observeEvent(input$capture, {

    for (i in unique(cars_react()$hp))
    {
      url = "https://oscar.com/prweb/PRRestService/"
      parameters<-'{
      "Reference":"Account"
      ,"ReferenceValue":""
      }'
      b<-fromJSON(parameters)
      b["ReferenceValue"]=i
      r <- POST(url, body = parameters,encode = "json")
      r_c<-toJSON(content(r))
      print(r_c)
    }

  })

}

)

Old answer

It is not clear from your question how, where and how often you want to use the vector of your reactive data frame. But it is an important question, since the concept of reactivity and how to access it is very hard to grasp when you come from a pure non reactive R environment.

Below is a simple example app which shows how to access vectors in reactive data frames, and how they could be used.

I hope it helps to get a better understanding of reactivity in shiny.

library(dplyr)
library(shiny)

shinyApp(ui = fluidPage(

  sidebarLayout(

    sidebarPanel(
    selectInput(inputId = "cyl",
                label = "Number cylinders:",
                choices = c("all",sort(unique(mtcars$cyl))),
                selected = "all"),
    actionButton("capture",
                 "capture value")

  ), # closes sidebarPanel


    mainPanel(

      tableOutput("text"),
      tableOutput("text2"),
      tableOutput("text3"),
      tableOutput("table")

  ) # closes mainPanel
  ) # closes sidebarLayout    

), # closes fluidPage

  server = function(input, output) {

# some example reactive data    
cars_react <- reactive({

  mtcars %>% 
    filter(cyl == input$cyl | input$cyl == "all")

  })

# simply global assignment of a reactive vector
observeEvent(cars_react(), {

    # here is a globally assigned vector taken from the reactive data
    # reused in a render statement it will not react to change, since it is not reactive 

    test_vec3 <<- unique(cars_react()$hp)

    })

  # here a file is written to the working directory of your shiny app
  # everytime cars_react() changes write (and overwrite) vector to a file 
  observeEvent(cars_react(), {

    test_vec = unique(cars_react()$hp)

    saveRDS(test_vec, file = "test_vec.Rdata")

    })

  # same as above but the file is gradually growing and not overwritten
  # everytime cars_react() changes add vector to a (over several sessions growing) list
  observeEvent(cars_react(), {

    test_vec2 = unique(cars_react()$hp)

    if (file.exists("test_list.Rdata")) {

      temp = readRDS("test_list.Rdata")

      test_list = c(temp, list(test_vec2))

    } else {

    test_list = list(test_vec2)

    }

    saveRDS(test_list, file = "test_list.Rdata")


  })

  # here we access the reactive data with isolate and make it non-reactive, but can update the values through a button click
  text_vec <- eventReactive(input$capture, {

    isolate(unique(cars_react()$hp))

  })

  # output of our reactive data as table
  output$table <- renderTable({

    cars_react()

    })   

  # text output of globally assigned non-reactive vector test_vec3 (not changing!)
  output$text <- renderText({

    test_vec3

  })   

  # you can capture values of reactives with isolate, but then, they don't change anymore 
  # text output of isolated formely reactive vector unique(cars_react()$hp (not changing!)
  output$text2 <- renderText({

    isolate(unique(cars_react()$hp))

  })   

  # text output of new reactive vector (changes when input$capture button is clicked)
  output$text3 <- renderText({

    text_vec()

  })  

  }

)
TimTeaFan
  • 11,990
  • 2
  • 14
  • 32
  • Hi, Tim your solution almost answers my question in the working example you have mentioned when I change the number of cylinders to 6 and press capture value I am getting 110 105 123 175 I want to pass these numbers to an API string for example and return the response accordingly. How can I do that? Thanks !! – Rohit Oct 17 '19 at 15:13
  • I need to store the text_vec() values in a vector can I do that and pass the values to an API? – Rohit Oct 17 '19 at 17:48
  • That should be no problem, however without seeing your approach, the packages and api you are using it is hard to answer. It will be easier for us to help you if you elaborate a bit on what your trying to do and if you include a reproducible example even if it is not working. Either update this question (if that is still possible while being put on hold) or post a new one. – TimTeaFan Oct 17 '19 at 20:43
  • Hi, Tim, I have included the updated code with your example I need to pass the values from text_vec() each time to the API. – Rohit Oct 18 '19 at 14:56
  • I have updated my answer, but if you need further help please provide a working example, or at least an example which could work in theory, with a real API and some real values. – TimTeaFan Oct 20 '19 at 10:03
  • 1
    Thanks, Tim this is what I want. – Rohit Oct 22 '19 at 18:47