R shiny 中的本地持久数据存储,适用于已部署应用程序中的多个用户
Local, persistent data storage in R shiny for multiple users in deployed app
我在 R shiny 中构建了一个梦幻足球类型的选秀模拟器。为了持续保存已选择的球员,我在保存 table 时使用了全局赋值运算符 <<-
,因此它可以在应用程序的其他部分成为 'seen'。该功能的简短示例如下;
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(DT)
TeamData <- data.frame("Pick" = 1:26 , "Team" = paste("Team",1:26) , "Player" = character(26) )
Players <- paste("Player",LETTERS)
ui <- dashboardPagePlus(collapse_sidebar = TRUE,
header = dashboardHeaderPlus(),
sidebar = dashboardSidebar(collapsed = TRUE,
#####
sidebarMenu(
menuItem("Tab 1",tabName = "Tab_1"))
#####
),
body = dashboardBody(
fluidRow( column(4 ,
selectInput(inputId = "dropdownSelect" , choices = c(paste("Player",LETTERS[1:10])) , label = "Drop down List") , br() ,
actionButton(inputId = "draftButton" , label = "Draft")) ,
column(6 ,
dataTableOutput("draftBoard"))
)
)
)
server <- function(input, output, session) {
pick <- reactiveValues(num = 1)
# To display table upon opening
output$draftBoard <- DT::renderDataTable({
datatable(data = TeamData ,
rownames = FALSE,
class = "row-bordered hover stripe nowrap order-column" ,
options = list(dom = "t",
columnDefs = list(list(className = 'dt-center', targets = "_all")),
paging = F,
searching = F,
scrollX = F, # 'background-color', '#002651'; 'border-bottom-left-radius','5px';
info = F))
})
observeEvent(input$draftButton, {
# Using global assignment to save the drafted Player
TeamData$Player[pick$num] <<- input$dropdownSelect
# To display table after updating choices
output$draftBoard <- DT::renderDataTable({
datatable(data = TeamData ,
rownames = FALSE,
class = "row-bordered hover stripe nowrap order-column" ,
options = list(dom = "t",
columnDefs = list(list(className = 'dt-center', targets = "_all")),
paging = F,
searching = F,
scrollX = F,
info = F))
})
# +1 to count
pick$num <- pick$num + 1
updateSelectInput(session , inputId = "dropdownSelect" , choices = setdiff(Players, TeamData$Player))
})
}
shinyApp(ui = ui, server = server)
在使用 shinyapps.io 部署应用程序并共享 link 供其他人使用后,我发现(艰难的方式)以这种方式进行全局分配不会让应用程序按预期工作,当多人使用该应用程序时,其他人的草稿选择会出现在他们的会话中,以及许多其他问题。
阅读了 R 中的持久数据存储后,我仍然不确定如何编写应用程序代码使其能够:
a) 被应用程序的其他部分'seen';这相当于 TeamData df,可以在应用程序的其他区域保存和访问被征召者。
b) 这样当与多人共享时,每个人都有自己的本地化应用程序会话,而不会覆盖彼此的工作。
如能提供任何帮助或material,我们将不胜感激!
使用 reactive
或 reactiveValue
来存储您的 table。它可以在您的整个应用程序中访问,但其他同时用户无法访问。下面是一个最小的例子。
这是一个很容易犯的错误。 shinyapps.io 通常会有一个 R 实例为多个用户服务。这意味着全局存储的任何内容,即使用 <<-
,将影响/对该实例中的所有用户可见。
library(shiny)
ui <- fluidPage(
selectInput(inputId = "drp_players", choices = paste("Player", LETTERS), label = "dropdown"),
actionButton(inputId = "btn_draft" , label = "Draft"),
tableOutput("table")
)
server <- function(input, output, session) {
#Reactive Value to Store Dataframe
reactives <- reactiveValues(
df_draftboard = data.frame(
pick = seq(1:26),
team = paste("Team", 1:26),
player = "",
stringsAsFactors = FALSE
)
)
#Table Output
output$table <- renderTable({
reactives$df_draftboard
})
#Draft Button is Pressed
observeEvent(input$btn_draft, {
#Work out which pick number we are up to
picknumber <- sum(reactives$df_draftboard$player != "") + 1
#Add picked player to draft board
reactives$df_draftboard$player[picknumber] <- input$drp_players
#Update dropdown
updateSelectInput(session, "drp_players", choices = setdiff(paste("Player", LETTERS), reactives$df_draftboard$player), label = "dropdown")
})
}
shinyApp(ui, server)
我在 R shiny 中构建了一个梦幻足球类型的选秀模拟器。为了持续保存已选择的球员,我在保存 table 时使用了全局赋值运算符 <<-
,因此它可以在应用程序的其他部分成为 'seen'。该功能的简短示例如下;
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(DT)
TeamData <- data.frame("Pick" = 1:26 , "Team" = paste("Team",1:26) , "Player" = character(26) )
Players <- paste("Player",LETTERS)
ui <- dashboardPagePlus(collapse_sidebar = TRUE,
header = dashboardHeaderPlus(),
sidebar = dashboardSidebar(collapsed = TRUE,
#####
sidebarMenu(
menuItem("Tab 1",tabName = "Tab_1"))
#####
),
body = dashboardBody(
fluidRow( column(4 ,
selectInput(inputId = "dropdownSelect" , choices = c(paste("Player",LETTERS[1:10])) , label = "Drop down List") , br() ,
actionButton(inputId = "draftButton" , label = "Draft")) ,
column(6 ,
dataTableOutput("draftBoard"))
)
)
)
server <- function(input, output, session) {
pick <- reactiveValues(num = 1)
# To display table upon opening
output$draftBoard <- DT::renderDataTable({
datatable(data = TeamData ,
rownames = FALSE,
class = "row-bordered hover stripe nowrap order-column" ,
options = list(dom = "t",
columnDefs = list(list(className = 'dt-center', targets = "_all")),
paging = F,
searching = F,
scrollX = F, # 'background-color', '#002651'; 'border-bottom-left-radius','5px';
info = F))
})
observeEvent(input$draftButton, {
# Using global assignment to save the drafted Player
TeamData$Player[pick$num] <<- input$dropdownSelect
# To display table after updating choices
output$draftBoard <- DT::renderDataTable({
datatable(data = TeamData ,
rownames = FALSE,
class = "row-bordered hover stripe nowrap order-column" ,
options = list(dom = "t",
columnDefs = list(list(className = 'dt-center', targets = "_all")),
paging = F,
searching = F,
scrollX = F,
info = F))
})
# +1 to count
pick$num <- pick$num + 1
updateSelectInput(session , inputId = "dropdownSelect" , choices = setdiff(Players, TeamData$Player))
})
}
shinyApp(ui = ui, server = server)
在使用 shinyapps.io 部署应用程序并共享 link 供其他人使用后,我发现(艰难的方式)以这种方式进行全局分配不会让应用程序按预期工作,当多人使用该应用程序时,其他人的草稿选择会出现在他们的会话中,以及许多其他问题。
阅读了 R 中的持久数据存储后,我仍然不确定如何编写应用程序代码使其能够:
a) 被应用程序的其他部分'seen';这相当于 TeamData df,可以在应用程序的其他区域保存和访问被征召者。
b) 这样当与多人共享时,每个人都有自己的本地化应用程序会话,而不会覆盖彼此的工作。
如能提供任何帮助或material,我们将不胜感激!
使用 reactive
或 reactiveValue
来存储您的 table。它可以在您的整个应用程序中访问,但其他同时用户无法访问。下面是一个最小的例子。
这是一个很容易犯的错误。 shinyapps.io 通常会有一个 R 实例为多个用户服务。这意味着全局存储的任何内容,即使用 <<-
,将影响/对该实例中的所有用户可见。
library(shiny)
ui <- fluidPage(
selectInput(inputId = "drp_players", choices = paste("Player", LETTERS), label = "dropdown"),
actionButton(inputId = "btn_draft" , label = "Draft"),
tableOutput("table")
)
server <- function(input, output, session) {
#Reactive Value to Store Dataframe
reactives <- reactiveValues(
df_draftboard = data.frame(
pick = seq(1:26),
team = paste("Team", 1:26),
player = "",
stringsAsFactors = FALSE
)
)
#Table Output
output$table <- renderTable({
reactives$df_draftboard
})
#Draft Button is Pressed
observeEvent(input$btn_draft, {
#Work out which pick number we are up to
picknumber <- sum(reactives$df_draftboard$player != "") + 1
#Add picked player to draft board
reactives$df_draftboard$player[picknumber] <- input$drp_players
#Update dropdown
updateSelectInput(session, "drp_players", choices = setdiff(paste("Player", LETTERS), reactives$df_draftboard$player), label = "dropdown")
})
}
shinyApp(ui, server)