【问题标题】:Storing a reactive output in a vector - Shiny R将反应输出存储在向量中 - Shiny R
【发布时间】:2019-10-16 18:54:42
【问题描述】:

我正在构建一个闪亮的应用程序。我使用了一些过滤器并渲染了一个数据框,并且数据框根据用户输入动态变化。但是我无法将数据框中的特定列值存储到向量中。我每次都需要将反应输出存储到一个向量中,以便以后可以再次使用这些值。这里的值存储在 text_vec 中,我需要将其传递给 API,但我无法从 text_vec 访问值,我必须每次将更新后的值传递给 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)
    }


  }


)

【问题讨论】:

  • 如果您包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出,则会更容易为您提供帮助。

标签: r shiny


【解决方案1】:

让数据帧在 Shiny 应用程序中使用的所有环境中持久存在的一种简单方法是使用“

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

# instead of
a <- b

【讨论】:

    【解决方案2】:

    ** 更新答案**

    根据您更新的答案,我会将您的 API 调用包装到 observeEvent 中,一旦按下操作按钮就会触发。由于您没有提供带有一些真实代码的工作示例,因此我不确定下面的示例是否有帮助。我进一步假设您的 for loop 是正确且有效的(就我而言,如果没有真正的 API 和一些实际值,我无法知道)。

    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)
        }
    
      })
    
    }
    
    )
    

    旧答案

    从您的问题中不清楚您希望如何、在何处以及多久使用一次反应式数据框的向量。但这是一个重要的问题,因为当您来自纯非反应式 R 环境时,反应性的概念以及如何访问它是非常难以掌握的。

    下面是一个简单的示例应用程序,它展示了如何访问响应式数据帧中的向量,以及如何使用它们。

    我希望它有助于更​​好地理解闪亮的反应性。

    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()
    
      })  
    
      }
    
    )
    

    【讨论】:

    • 嗨,蒂姆,您的解决方案几乎回答了我在工作示例中提到的问题,当我将气缸数更改为 6 并按下捕获值时,我得到 110 105 123 175 我想传递这些数字以 API 字符串为例,并相应地返回响应。我怎样才能做到这一点?谢谢!!
    • 我需要将 text_vec() 值存储在向量中,我可以这样做并将值传递给 API 吗?
    • 这应该没问题,但是没有看到你的方法,你正在使用的包和api很难回答。如果您详细说明您尝试做什么,并且如果您包含一个可重现的示例,即使它不起作用,我们也会更容易为您提供帮助。更新这个问题(如果在被搁置的情况下仍然可能)或发布一个新问题。
    • 嗨,蒂姆,我已将更新后的代码包含在您的示例中,我需要每次将 text_vec() 中的值传递给 API。
    • 谢谢,Tim 这就是我想要的。
    猜你喜欢
    • 1970-01-01
    • 2014-05-11
    • 2021-06-19
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多