简体   繁体   中英

Modifying a Non-Reactive R Dataframe while running Shiny App

I'm building my first Shiny app and I'm running into some trouble.

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. But while it's running, this has no effect on user_features3. I think this may be because R is busy with the 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.

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

In addition to all of the other shiny tutorials, I suggest you read about variable scope in shiny, specifically statements such as

  • "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;
  • "This local copy of [this variable] is not be visible in other sessions" , talking about a variable stored within the server function; and
  • "Objects defined in global.R are similar to those defined in app.R outside of the server function definition" .

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


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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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