避免 Shiny 应用程序中不必要的负载
Avoid unnecessary load in Shiny app
我有一个 eventReactive
函数可以加载到两个数据集中。可以选择每个数据集,但它们都加载在同一个 eventReactive
中。但是,如果用户只更改两个数据集之一,我不希望它们都加载,而只加载已更改的数据集。我知道使用两个操作按钮会容易得多,但我需要将它合二为一。请在下面找到示例代码。
因此在示例中,我只想再次执行变量已更改的那部分代码。
ui.r:
library(shiny)
# Define UI for dataset viewer application
shinyUI(fluidPage(
# Application title
titlePanel("Reactivity"),
# Sidebar with controls to provide a caption, select a dataset,
# and specify the number of observations to view. Note that
# changes made to the caption in the textInput control are
# updated in the output area immediately as you type
sidebarLayout(
sidebarPanel(
textInput("caption", "Caption:", "Data Summary"),
actionButton('Go','Go'),
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
selectInput("dataset2", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
numericInput("obs", "Number of observations to view:", 10)
),
# Show the caption, a summary of the dataset and an HTML
# table with the requested number of observations
mainPanel(
h3(textOutput("caption", container = span)),
verbatimTextOutput('one'),
verbatimTextOutput('two'),
verbatimTextOutput("summary"),
verbatimTextOutput("summary2")#,
# tableOutput("view"),
# tableOutput("view2")
)
)
))
server.r
library(shiny)
library(datasets)
# Define server logic required to summarize and view the selected
# dataset
shinyServer(function(input, output) {
# By declaring datasetInput as a reactive expression we ensure
# that:
#
# 1) It is only called when the inputs it depends on changes
# 2) The computation and result are shared by all the callers
# (it only executes a single time)
#
datasetInput <- eventReactive(input$Go,{
##Only run if input$dataset has changed##
withProgress(message='Loading 1:This should take very long....',value=0,{
for(i in 1:5){
Sys.sleep(1)
incProgress(i/5)
}
x<-switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
###only run if input$dataset2 has changed
withProgress(message='Loading 2:This should take even longer....',value=0,{
for(i in 1:5){
Sys.sleep(1.5)
incProgress(i/5)
}
y<-switch(input$dataset2,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
return(list(x=x,y=y,input1=input$dataset,input2=input$dataset2))
})
# The output$caption is computed based on a reactive expression
# that returns input$caption. When the user changes the
# "caption" field:
#
# 1) This function is automatically called to recompute the
# output
# 2) The new caption is pushed back to the browser for
# re-display
#
# Note that because the data-oriented reactive expressions
# below don't depend on input$caption, those expressions are
# NOT called when input$caption changes.
output$caption <- renderText({
input$caption
})
# The output$summary depends on the datasetInput reactive
# expression, so will be re-executed whenever datasetInput is
# invalidated
# (i.e. whenever the input$dataset changes)
output$summary <- renderPrint({
dataset <- datasetInput()$x
summary(dataset)
})
output$summary2 <- renderPrint({
dataset <- datasetInput()$y
summary(dataset)
})
# The output$view depends on both the databaseInput reactive
# expression and input$obs, so will be re-executed whenever
# input$dataset or input$obs is changed.
output$view <- renderTable({
head(datasetInput()$x, n = input$obs)
})
output$view2 <- renderTable({
head(datasetInput()$y, n = input$obs)
})
output$one<-renderText(datasetInput()$input1)
output$two<-renderText(datasetInput()$input2)
})
我已经尝试过这样的事情:if(datasetInput()$input1 != input$dataset){execute...}
但它不起作用,可能是因为您在同一个函数中创建的反应函数中使用了一个值...
您可以将两个数据加载步骤分成 reactive
表达式,您的 eventReactive
依赖于这些表达式。这样,当您单击 Go 时,如果它们更改了输入值,它会调用两个反应式表达式,但如果输入未更新则不会调用。例如:
library(shiny)
library(datasets)
ui = fluidPage(
# Application title
titlePanel("Reactivity"),
sidebarLayout(
sidebarPanel(
textInput("caption", "Caption:", "Data Summary"),
actionButton('Go','Go'),
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
selectInput("dataset2", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
numericInput("obs", "Number of observations to view:", 10)
),
mainPanel(
h3(textOutput("caption", container = span)),
verbatimTextOutput('one'),
verbatimTextOutput('two'),
verbatimTextOutput("summary"),
verbatimTextOutput("summary2")
)
)
)
server = function(input, output) {
dat1 = reactive({
withProgress(message='Loading 1:This should take very long....',value=0,{
for(i in 1:5){
Sys.sleep(1)
incProgress(i/5)
}
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
})
dat2 = reactive({
withProgress(message='Loading 2:This should take even longer....',value=0,{
for(i in 1:5){
Sys.sleep(1.5)
incProgress(i/5)
}
switch(input$dataset2,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
})
datasetInput <- eventReactive(input$Go,{
x = dat1()
y = dat2()
return(list(x=x,y=y,input1=input$dataset,input2=input$dataset2))
})
output$caption <- renderText({
input$caption
})
output$summary <- renderPrint({
dataset <- datasetInput()$x
summary(dataset)
})
output$summary2 <- renderPrint({
dataset <- datasetInput()$y
summary(dataset)
})
output$view <- renderTable({
head(datasetInput()$x, n = input$obs)
})
output$view2 <- renderTable({
head(datasetInput()$y, n = input$obs)
})
output$one<-renderText(datasetInput()$input1)
output$two<-renderText(datasetInput()$input2)
}
shiny::shinyApp(ui,server)
我有一个 eventReactive
函数可以加载到两个数据集中。可以选择每个数据集,但它们都加载在同一个 eventReactive
中。但是,如果用户只更改两个数据集之一,我不希望它们都加载,而只加载已更改的数据集。我知道使用两个操作按钮会容易得多,但我需要将它合二为一。请在下面找到示例代码。
因此在示例中,我只想再次执行变量已更改的那部分代码。 ui.r:
library(shiny)
# Define UI for dataset viewer application
shinyUI(fluidPage(
# Application title
titlePanel("Reactivity"),
# Sidebar with controls to provide a caption, select a dataset,
# and specify the number of observations to view. Note that
# changes made to the caption in the textInput control are
# updated in the output area immediately as you type
sidebarLayout(
sidebarPanel(
textInput("caption", "Caption:", "Data Summary"),
actionButton('Go','Go'),
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
selectInput("dataset2", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
numericInput("obs", "Number of observations to view:", 10)
),
# Show the caption, a summary of the dataset and an HTML
# table with the requested number of observations
mainPanel(
h3(textOutput("caption", container = span)),
verbatimTextOutput('one'),
verbatimTextOutput('two'),
verbatimTextOutput("summary"),
verbatimTextOutput("summary2")#,
# tableOutput("view"),
# tableOutput("view2")
)
)
))
server.r
library(shiny)
library(datasets)
# Define server logic required to summarize and view the selected
# dataset
shinyServer(function(input, output) {
# By declaring datasetInput as a reactive expression we ensure
# that:
#
# 1) It is only called when the inputs it depends on changes
# 2) The computation and result are shared by all the callers
# (it only executes a single time)
#
datasetInput <- eventReactive(input$Go,{
##Only run if input$dataset has changed##
withProgress(message='Loading 1:This should take very long....',value=0,{
for(i in 1:5){
Sys.sleep(1)
incProgress(i/5)
}
x<-switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
###only run if input$dataset2 has changed
withProgress(message='Loading 2:This should take even longer....',value=0,{
for(i in 1:5){
Sys.sleep(1.5)
incProgress(i/5)
}
y<-switch(input$dataset2,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
return(list(x=x,y=y,input1=input$dataset,input2=input$dataset2))
})
# The output$caption is computed based on a reactive expression
# that returns input$caption. When the user changes the
# "caption" field:
#
# 1) This function is automatically called to recompute the
# output
# 2) The new caption is pushed back to the browser for
# re-display
#
# Note that because the data-oriented reactive expressions
# below don't depend on input$caption, those expressions are
# NOT called when input$caption changes.
output$caption <- renderText({
input$caption
})
# The output$summary depends on the datasetInput reactive
# expression, so will be re-executed whenever datasetInput is
# invalidated
# (i.e. whenever the input$dataset changes)
output$summary <- renderPrint({
dataset <- datasetInput()$x
summary(dataset)
})
output$summary2 <- renderPrint({
dataset <- datasetInput()$y
summary(dataset)
})
# The output$view depends on both the databaseInput reactive
# expression and input$obs, so will be re-executed whenever
# input$dataset or input$obs is changed.
output$view <- renderTable({
head(datasetInput()$x, n = input$obs)
})
output$view2 <- renderTable({
head(datasetInput()$y, n = input$obs)
})
output$one<-renderText(datasetInput()$input1)
output$two<-renderText(datasetInput()$input2)
})
我已经尝试过这样的事情:if(datasetInput()$input1 != input$dataset){execute...}
但它不起作用,可能是因为您在同一个函数中创建的反应函数中使用了一个值...
您可以将两个数据加载步骤分成 reactive
表达式,您的 eventReactive
依赖于这些表达式。这样,当您单击 Go 时,如果它们更改了输入值,它会调用两个反应式表达式,但如果输入未更新则不会调用。例如:
library(shiny)
library(datasets)
ui = fluidPage(
# Application title
titlePanel("Reactivity"),
sidebarLayout(
sidebarPanel(
textInput("caption", "Caption:", "Data Summary"),
actionButton('Go','Go'),
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
selectInput("dataset2", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
numericInput("obs", "Number of observations to view:", 10)
),
mainPanel(
h3(textOutput("caption", container = span)),
verbatimTextOutput('one'),
verbatimTextOutput('two'),
verbatimTextOutput("summary"),
verbatimTextOutput("summary2")
)
)
)
server = function(input, output) {
dat1 = reactive({
withProgress(message='Loading 1:This should take very long....',value=0,{
for(i in 1:5){
Sys.sleep(1)
incProgress(i/5)
}
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
})
dat2 = reactive({
withProgress(message='Loading 2:This should take even longer....',value=0,{
for(i in 1:5){
Sys.sleep(1.5)
incProgress(i/5)
}
switch(input$dataset2,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
})
datasetInput <- eventReactive(input$Go,{
x = dat1()
y = dat2()
return(list(x=x,y=y,input1=input$dataset,input2=input$dataset2))
})
output$caption <- renderText({
input$caption
})
output$summary <- renderPrint({
dataset <- datasetInput()$x
summary(dataset)
})
output$summary2 <- renderPrint({
dataset <- datasetInput()$y
summary(dataset)
})
output$view <- renderTable({
head(datasetInput()$x, n = input$obs)
})
output$view2 <- renderTable({
head(datasetInput()$y, n = input$obs)
})
output$one<-renderText(datasetInput()$input1)
output$two<-renderText(datasetInput()$input2)
}
shiny::shinyApp(ui,server)