У меня есть сценарий, который я хочу добавить в свое приложение Shiny, и исходный сценарий можно упростить до следующего:
plot(c(1:3),c(2,4,6), main = "This is first plot I want displayed")
a <- menu(c(1:5), title = "what would you like to change the first point to?")
plot(c(1:3),c(a,4,6), main = "This is second plot I want displayed")
b <- menu(c(1:5), title = "what would you like to change the second point to?")
plot(c(1:3),c(a,b,6), main = "This is second plot I want displayed")
Приведенный выше скрипт строит первый график, затем ожидает ввода пользователем перед построением второго и снова ждет ввода пользователя перед построением третьего.
Однако, когда я пытаюсь преобразовать его в блестящее приложение, как показано ниже, оно никогда не обновляет первый или второй график, и то, что я пытался остановить для пользовательского ввода, где показано, не сработало.
Я пытался использовать req(), но, кажется, он полностью останавливает скрипт, поэтому последние вещи вообще не запускаются, и вам нужно запустить весь скрипт заново.
Итак, как я могу заставить его отображать все графики последовательно и как я могу остановить скрипт и дождаться ввода, прежде чем продолжить?
if (interactive()){
ui <- fluidPage(
actionButton("button","Click me"),
selectInput("input", "Input", c(1:10)),
textOutput("text"),
plotOutput("plot")
)
server <- function(input, output) {
a<-1
observeEvent(input$button, {
output$plot <- renderPlot(plot(c(1:3),c(2,4,6), main = "This is first plot I want displayed"))
output$text <- renderText("Please select a number to multiply the first point with")
#This is where I want the script to wait for user input
output$plot <- renderPlot(plot(c((1),(2),(3)),c((input$input),(a),(3)), main = "This is plot the second plot"))
a<-a+1
#Here I want the script to wait for user input again
output$plot <- renderPlot(plot(c((1),(2),(3)),c((input$input),(a),(3)), main = "This is plot the third plot"))
})
}
shinyApp(ui=ui, server=server)
}
Цель состоит в том, чтобы он обновлял графики, когда они отображались в коде, и ждал ввода данных пользователем до тех пор, пока скрипт не продолжит работу, вместо того, чтобы просто продолжать работу.
Честно говоря, я не уверен на 100%, знаю ли я, чего вы ожидаете, даже прочитав ваш текст 5 раз. У меня есть предположение ;-).
Ваша функция pause
, которая заставляет графики отображать один шаг за другим, может быть выполнена с помощью invalidateLater
. Это должно «жить» внутри реактивного значения. Я точно не знаю, кто автор этой функции, я сохранил ее в своих сниппетах (слава неизвестному).
Чтобы отобразить график или запустить сценарий на основе ввода пользователя, попробуйте перехватить его с помощью оператора if
.
Надеюсь это поможет :-).
library(shiny)
if (interactive()){
ui <- fluidPage(
selectInput("input", "Input", c(1:10)),
actionButton("apply", "Apply"),
textOutput("text"),
plotOutput("plot")
)
server <- function(input, output, session) {
rv <- reactiveValues(i = 0)
maxIter <- 10
observeEvent(input$apply, {
rv$i <- 0
observe({
isolate({
rv$i <- rv$i + 1
})
if (isolate(rv$i) < maxIter){
invalidateLater(2000, session)
}
})
})
output$plot <- renderPlot( {
if (rv$i > 0) {
if (input$input <= 4) {
plot(c((rv$i*1),(rv$i*2),(rv$i*3)),c((1),(2),(3)), main = sprintf("Input <= 4; Round %i", rv$i), type = "l")
} else {
plot(c((rv$i*1),(rv$i*5),(rv$i*4)),c((1),(2),(3)), main = sprintf("Input > 4; Round %i", rv$i), type = "l")
}
} else {
plot(c(1:3),c(2,4,6), main = "This is first plot")
}
})
}
shinyApp(ui=ui, server=server)
}
Возможно, это то, что вы хотите.
req
используется для отображения только тогда, когда переменная доступна. Вам нужно создать второй renderUI
на сервере, так как вы не можете использовать req
в части пользовательского интерфейса.
if (interactive()){
ui <- fluidPage(
plotOutput("plot1"),
numericInput ("num1", "Please select a number to multiply the first point with", NA, 1, 10),
plotOutput("plot2"),
uiOutput("num2"),
plotOutput("plot3")
)
server <- function(input, output) {
output$plot1 <- renderPlot(plot(c(1:3),c(2,4,6), main = "This is first plot I want displayed"))
output$plot2 <- renderPlot({
req(input$num1)
plot(c(1:3),c(2*(input$num1),4,(6)),
main = "This is plot the second plot"
)
}
)
output$plot3 <- renderPlot({
req(input$num1, input$num2)
plot(c(1:3),c(2*(input$num1)+(input$num2),4,(6)),
main = "This is plot the third plot"
)
}
)
output$num2 <- renderUI({
req(input$num1)
numericInput ("num2", "Please select a number to add to first point", NA, 1, 10)
})
}
shinyApp(ui=ui, server=server)
}
Попытаюсь уточнить