我有一个我想要的时间函数,然后在UI上显示执行该函数需要多长时间。如何重新激活该功能的执行时间?我试图将变量放在反应函数中,围绕函数等。我只想计算反应函数运行多长时间然后显示它。我试图不使用其他包。
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
sidebarPanel(
# User Input Text Box
textInput(inputId = "userText",
label = "",
placeholder = "Type in a partial sentence here..."),
verbatimTextOutput(outputId = "textInput", placeholder = TRUE),
# Show amount of execution time
verbatimTextOutput(outputId = "timer", placeholder = TRUE)
))
server <- function(input, output) {
# Declare Timer variables
startTime <- Sys.time()
endTime <- Sys.time()
# Some function to time: Trivial Paste Function
textToDisplay <- reactive({
req(input$userText)
startTime <- Sys.time()
textToDisplay <- paste("This is the user input text: ", input$userText)
endTime <- Sys.time()
return(textToDisplay)
})
# Display pasted text
output$textInput <- renderText({
req(input$userText)
textToDisplay()
})
# Display execution time
output$timer <- renderText({
req(input$userText)
paste0("Executed in: ",((endTime - startTime)*1000)," milliseconds")
})
}
# Run the application
shinyApp(ui = ui, server = server)
上述代码未正确更新或显示正确的时差。
答案 0 :(得分:3)
Ah, the problem is that startTime
and endTime
aren't reactive values, so when they change they don't cause renderText
to be invalidated and rerun and they don't persist properly outside the reactive expressions.
Just define a reactiveValues
object, and make startTime
and endTime
part of that.
Replace the part where you define timer variables with:
rv <- reactiveValues()
Then, each time you call on startTime
and endTime
, use rv$startTime
and rv$endTime
.
You still won't see a result because textToDisplay
runs too quickly, but if you make those changes and add Sys.sleep(2)
into textToDisplay
you'll see that it works properly.
答案 1 :(得分:1)
I think there is a bit of unnecessary code there. Your definition of startTime
and endTime
both within server
and the individual reactive chunks is confusing (both to you and the readers); most certainly both locations are not required, and since I prefer the use of system.time
, I suggest neither location is necessary.
There are two ways to deal with getting two return values (data and elapsed time) from a chunk: (1) return a list
, and (2) reactiveValues()
.
Keeping your ui
and shinyApp
...
For the first option (list
), the server
component becomes:
server <- function(input, output) {
mydat <- eventReactive(input$userText, {
req(input$userText)
tm <- system.time({
Sys.sleep(runif(1))
out <- paste("This is the user input text:", sQuote(input$userText))
})
list(x=out, elapsed=tm['elapsed'])
})
# Display pasted text
output$textInput <- renderText({
req(mydat())
mydat()$x
})
# Display execution time
output$timer <- renderText({
req(mydat())
paste0("Executed in: ", round(mydat()$elapsed*1000), " milliseconds")
})
}
For the second option, try:
server <- function(input, output) {
times <- reactiveVal()
mydat <- reactiveVal()
# operates in side-effect
observeEvent(input$userText, {
req(input$userText)
tm <- system.time({
Sys.sleep(runif(1))
out <- paste("This is the user input text:", sQuote(input$userText))
})
times(tm['elapsed'])
mydat(out)
})
# Display pasted text
output$textInput <- renderText({
req(mydat())
mydat()
})
# Display execution time
output$timer <- renderText({
req(times())
paste0("Executed in: ", round(times()*1000), " milliseconds")
})
}
(Instead of two reactiveVal()
variables, you can also use @divibisan's suggestion to use reactiveValues()
, the same end-result.)
答案 2 :(得分:0)
我使用的方法是你的建议@ r2evans和@divibisan的组合。我使用了reactiveValues,因为我认为它是用户可读的,可以很容易地扩展到其他用途。我按照建议使用了system.time。运行该函数时,它会更新无功值,并且return语句控制从函数返回适当的值。
server <- function(input, output) {
options(digits.secs=2)
# Declare Timer variables
rv <- reactiveValues(
exTime = Sys.time()
)
# Trivial Paste Function
textToDisplay <- reactive({
req(input$userText)
t <- system.time({
textToDisplay <- paste("This is the user input text: ",
input$userText)
})
rv$exTime <- t[[3]]
return(textToDisplay)
})
# Display pasted text
output$textInput <- renderText({
req(input$userText)
textToDisplay()
})
# Display execution time
output$timer <- renderText({
req(input$userText)
paste0("Executed in: ",((rv$exTime)*1000)," milliseconds")
})
}
正如@divibisan建议的那样,这将显示0,因为代码运行得如此之快。您可以使用system.time()
增加从options(digits.secs=2)
返回的数字,我在服务器代码的顶部添加了这些数字。对于我的真实功能,这使我在Windows中运行了10毫秒的精度。