简体   繁体   English

运行Shiny App时修改非反应性R数据框

[英]Modifying a Non-Reactive R Dataframe while running Shiny App

I'm building my first Shiny app and I'm running into some trouble. 我正在构建我的第一个Shiny应用程序,但遇到了一些麻烦。

When I register a new user for the app, I need to add a row with some empty values to a dataframe, that will be used to generate recommendations. 当我为该应用程序注册新用户时,我需要在数据框中添加一行包含一些空值的行,以用于生成建议。

user_features3 <- rbind(user_features3,c(612,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0))

This works alright while the app isn't running, and the 612th row is added. 在应用程序未运行时,它可以正常运行,并添加了第612行。 But while it's running, this has no effect on user_features3. 但是,在运行时,这对user_features3无效。 I think this may be because R is busy with the webapp. 我认为这可能是因为R忙于webapp。

If I make a reactive value, say values <- reactiveValues() and then value$df <- user_features3 , I can modify the values in this reactive one, but I am unable to access the non-reactive one in a similar manner while the app is running. 如果我创建一个无功值,说values <- reactiveValues() and then value$df <- user_features3 ,则可以修改此无功值,但是当应用正在运行。

I need to update it in real-time so that I can use it to generate movie recommendations. 我需要实时更新它,以便可以使用它生成电影推荐。 Any suggestions? 有什么建议么?

This solves your asked question, but modifying non-reactive variables can cause problems as well. 这可以解决您的问题,但是修改非反应变量也会引起问题。 In general, thinking about modifying a non-reactive variable within a shiny environment indicates perhaps you aren't thinking about how to scale or store or properly maintain the app state. 通常,考虑在shiny环境中修改非反应变量意味着您可能没有考虑如何扩展或存储或正确维护应用程序状态。 For instance, if you are expecting multiple users, then know that this data is not shared with the other users, it is the current-user only. 例如,如果您期望有多个用户,则知道该数据未与其他用户共享,则仅是当前用户。 There is no way around this using local variables. 使用局部变量无法解决此问题。 (If you need to "share" something between users, you really need a data backend such as some form of SQL, including SQLite. See: https://shiny.rstudio.com/articles/persistent-data-storage.html ) (如果需要在用户之间“共享”某些东西,则确实需要数据后端,例如某种形式的SQL,包括SQLite。请参阅: https : //shiny.rstudio.com/articles/persistent-data-storage.html

In addition to all of the other shiny tutorials, I suggest you read about variable scope in shiny, specifically statements such as 除了所有其他shiny教程之外,我建议您阅读闪亮的变量范围 ,特别是诸如

  • "A read-only data set that will load once, when Shiny starts, and will be available to each user session" , talking about data stored outside of the server function definition; “一个只读数据集,它将在Shiny启动时加载一次,并且将可用于每个用户会话” ,讨论了存储在server功能定义之外的数据;
  • "This local copy of [this variable] is not be visible in other sessions" , talking about a variable stored within the server function; “ [此变量]的本地副本在其他会话中不可见” ,谈论存储在server函数中的变量; and
  • "Objects defined in global.R are similar to those defined in app.R outside of the server function definition" . “在global.R中定义的对象类似于在服务器功能定义之外在app.R中定义的对象”

Having said that, two offered solutions. 话虽如此,但有两个提供了解决方案。

Reactive Frame (encouraged!) 反应框架(鼓励!)

library(shiny)

ui <- fluidPage(
  # App title ----
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      textInput(inputId = "sometext", label = "Some Text:",
                placeholder = "(nothing meaningful)"),
      actionButton(inputId = "addnow", label = "Add!")
    ),
    mainPanel(
      tableOutput("myframe")
    )
  )
)

server <- function(input, output, session) {
  rxframe <- reactiveVal(
    data.frame(txt = character(0), i = integer(0),
               stringsAsFactors = FALSE)
  )
  observeEvent(input$addnow, {
    newdat <- data.frame(txt = isolate(input$sometext),
                         i = nrow(rxframe()) + 1L,
                         stringsAsFactors = FALSE)
    rxframe( rbind(rxframe(), newdat, stringsAsFactors = FALSE) )
  })
  output$myframe <- shiny::renderTable( rxframe() )
}

shinyApp(ui, server)

This example uses shiny::reactiveVal , though it would be just as easy to use shiny::reactiveValues (if multiple reactive variables are being used). 本例使用shiny::reactiveVal ,虽然这将是一样容易使用的shiny::reactiveValues (如果正在使用多个反应变量)。


Non-Reactive Frame (discouraged) 非反应式框架(不推荐使用)

library(shiny)

ui <- fluidPage(
  # App title ----
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      textInput(inputId = "sometext", label = "Some Text:",
                placeholder = "(nothing meaningful)"),
      actionButton(inputId = "addnow", label = "Add!")
    ),
    mainPanel(
      tableOutput("myframe")
    )
  )
)

server <- function(input, output, session) {
  nonrxframe <- data.frame(txt = character(0), i = integer(0),
                           stringsAsFactors = FALSE)
  output$myframe <- shiny::renderTable({
    req(input$addnow)
    nonrxframe <<- rbind(nonrxframe,
                         data.frame(txt = isolate(input$sometext),
                                    i = nrow(nonrxframe) + 1L,
                                    stringsAsFactors = FALSE),
                         stringsAsFactors = FALSE)
    nonrxframe
  })
}

shinyApp(ui, server)

Both allow sequencing as the screenshots below demonstrate. 两者都允许排序,如下面的屏幕快照所示。 Many will argue that the first (reactive) example is cleaner and safer. 许多人会争辩说,第一个(反应性)示例更清洁,更安全。 (Just the use of <<- is deterrent enough for me!) (仅使用<<-就足以威慑我了!)

将数据添加到非反应性框架的步骤

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM