r闪亮:按下按钮时eventReactive没有反应

Posted

技术标签:

【中文标题】r闪亮:按下按钮时eventReactive没有反应【英文标题】:r shiny: eventReactive is not reacting when the button is pressed 【发布时间】:2018-08-01 07:17:00 【问题描述】:

下面是我的代码。它可能看起来有点长,但实际上它是一个非常简单的应用程序。

用户应该上传一个很小的数据框(如果您在美国,则为 x.csv,如果您在欧洲,则为 x_Europe.csv)。然后用户应该点击按钮开始计算。最后,用户应该能够以数据框的形式下载这些计算的结果。

我的问题:上传文件后,当我单击“do_it”操作按钮时 - 没有任何反应。我可以看到它,因为我的控制台上没有打印任何内容。为什么?毕竟,我的函数“main_calc”应该是 eventReactive 到 input$do_it?为什么 main_calc 中的所有计算只有在用户尝试下载结果后才开始发生?

重要提示:将“数据”函数与 main_calc 分开对我来说很重要。

非常感谢!

首先,在您的工作目录中生成以下两个文件之一:

# generate file 'x.csv' to read in later in the app:
write.csv(data.frame(a = 1:4, b = 2:5), "x.csv", row.names = F)  # US file
write.csv2(data.frame(a = 1:4, b = 2:5), "x_Europe.csv", row.names = F)

这是闪亮应用的代码:

library(shiny)

ui <- fluidPage(
  # User should upload file x here:
  fileInput("file_x", label = h5("Upload file 'x.csv'!")),
  br(),
  actionButton("do_it", "Click Here First:"),
  br(),
  br(),
  textInput("user_filename","Save your file as:", value = "My file x"),
  downloadButton('file_down',"Save the output File:")
)

server <- function(input, output, session) 

  #----------------------------------------------------------------------
  # Function to read in either European (csv2) or American (csv) input:
  #----------------------------------------------------------------------

  ReadFile <- function(pathtofile, withheader = TRUE)

    test <- readLines(pathtofile, n = 1)  
    if (length(strsplit(test, split = ";")[[1]]) > 1) 
      print("Reading European CSV file")
      outlist <- list(myinput = read.csv2(pathtofile, header = TRUE),
                      europe.file = 1)
     else 
      print("Reading US CSV file")
      outlist <- list(myinput = read.csv(pathtofile, header = TRUE),
                      europe.file = 0)
    
    return(outlist)
  

  #----------------------------------------------------------------------
  # Data-related - getting the input file
  #----------------------------------------------------------------------  

  Data <- reactive(

    print("Starting reactive function 'Data'")
    # Input file:
    infile_x <- input$file_x
    myx <- ReadFile(infile_x$datapath)$myinput

    # European file?
    europe <- ReadFile(infile_x$datapath)$europe.file

    print("Finishing reactive function 'Data'")
    return(list(data = myx, europe = europe))

  )

  #----------------------------------------------------------------------
  # Main function that should read in the input and 'calculate' stuff
  # after the users clicks on the button 'do_it' - takes about 20 sec
  #----------------------------------------------------------------------

  main_calc <- eventReactive(input$do_it, 

    req(input$file_x)

    # Reading in the input file:
    x <- Data()$data
    print("Done reading in the data inside main_calc")

    # Running useless calculations - just to kill time:

    myvector <- matrix(unlist(x), ncol = 1, nrow = 1000)
    print("Starting calculations")

    for (i in seq_len(10)) 
      set.seed(12)
      mymatr <- matrix(abs(rnorm(1000000)), nrow = 1000)
      temp <- solve(mymatr) %*% myvector
    

    print("Finished calculations")

    # Creating a new file:
    y <- temp
    result = list(x = x, y = y)
    print("End of eventReactive function main_calc.")
    return(result)
  )   # end of main_calc

  #----------------------------------------------------------------------
  # The user should be able to save the output of main_calc as a csv file
  # using a string s/he specified for the file name:
  #----------------------------------------------------------------------

  output$file_down <- downloadHandler(
    filename = function() 
      paste0(input$user_filename, " ", Sys.Date(), ".csv") 
    ,
    content = function(file) 
      print("Europe Flag is:")
      print(Data()$europe)

      if (Data()$europe == 1) 
        x_out <- main_calc()$x
        print("Dimensions of x in downloadHandler are:")
        print(dim(x_out))        
        write.csv2(x_out, 
                   file,
                   row.names = FALSE)
       else 
        x_out <- main_calc()$x
        print("Dimensions of x in downloadHandler are:")
        print(dim(x_out))
        write.csv(x_out, 
                  file,
                  row.names = FALSE)
      
    
  )


  # end of server code  

shinyApp(ui, server)

【问题讨论】:

尝试将main_calc() 添加为downloadHandler 的第一行以创建依赖项 也许这个问题将有助于澄清:***.com/questions/33519816/…。 eventReactive 对象在事件发生时不会“运行”,它们只是被标记为无效。在实际向它们请求值之前,它们不会运行。因此,由于您在按下下载按钮之前不使用main_calc(),因此直到那时它才会运行。您可能希望 observeEventreactiveValues 对象进行此类交互。 有趣(也很疯狂!) - 我添加了 main_calc(),作为 downloadHandler 中的第一行。确实-在我单击按钮后进行了计算,但是:计算结束后,文件下载按钮非常小,当我单击它时,一切都崩溃了:“ self$downloads$set(name,list)中的警告(filename = filename, contentType = contentType, : 重新启动中断的 Promise 评估" 然后:运行中的错误 (timeoutMs) :期望单个字符串值:[type=character; extent=2]。 @MrFlick 但是如果我使用 observeEvent - 我不能返回任何东西,可以吗?如果我没有返回我需要下载的对象的函数(如 main_calc),我的 downloadHandler 应该下载什么? @user3245256 是的,你不能返回任何东西。这就是为什么您需要更新事件之外的 reactiveValues 对象中的值。看这个简单的例子:gist.github.com/aagarw30/69feeeb7e813788a753b71ef8c0877eb 【参考方案1】:

以下是解决方案 - 基于 MrFlick 的建议:

# generate file 'x.csv' to read in later in the app:
# write.csv(data.frame(a = 1:4, b = 2:5), "x.csv", row.names = F)
# write.csv2(data.frame(a = 1:4, b = 2:5), "x_Europe.csv", row.names = F)

library(shiny)
library(shinyjs)

ui <- fluidPage(
  # User should upload file x here:
  fileInput("file_x", label = h5("Upload file 'x.csv'!")),
  br(),
  actionButton("do_it", "Click Here First:"),
  br(),
  br(),
  textInput("user_filename","Save your file as:", value = "My file x"),
  downloadButton('file_down',"Save the output File:")
)

server <- function(input, output, session) 



  #----------------------------------------------------------------------
  # Function to read in either European (csv2) or American (csv) input:
  #----------------------------------------------------------------------

  ReadFile <- function(pathtofile, withheader = TRUE)

    test <- readLines(pathtofile, n = 1)  
    if (length(strsplit(test, split = ";")[[1]]) > 1) 
      print("Reading European CSV file")
      outlist <- list(myinput = read.csv2(pathtofile, header = TRUE),
                      europe.file = 1)
     else 
      print("Reading US CSV file")
      outlist <- list(myinput = read.csv(pathtofile, header = TRUE),
                      europe.file = 0)
    
    return(outlist)
  


  #----------------------------------------------------------------------
  # Data-related - getting the input file
  #----------------------------------------------------------------------  

  Data <- reactive(


    print("Starting reactive function Data")
    # Input file:
    infile_x <- input$file_x
    myx <- ReadFile(infile_x$datapath)$myinput

    # European file?
    europe <- ReadFile(infile_x$datapath)$europe.file

    print("Finishing reactive function 'Data'")
    return(list(data = myx, europe = europe))

  )

  #----------------------------------------------------------------------
  # Main function that should read in the input and 'calculate' stuff
  # after the users clicks on the button 'do_it' - takes about 20 sec
  #----------------------------------------------------------------------


  # Creating reactive Values:
  forout_reactive <- reactiveValues()

  observeEvent(input$do_it, 

    print("STARTING observeEvent")

    req(input$file_x)

    # Reading in the input file:
    x <- Data()$data
    print("Done reading in the data inside observeEvent")

    # Running useless calculations - just to kill time:

    myvector <- matrix(unlist(x), ncol = 1, nrow = 1000)
    print("Starting calculations")

    for (i in seq_len(10)) 
      set.seed(12)
      mymatr <- matrix(abs(rnorm(1000000)), nrow = 1000)
      temp <- solve(mymatr) %*% myvector
      # takes about 22 sec on a laptop

    print("Finished calculations")

    # Creating a new file:
    y <- temp
    forout_reactive$x = x
    forout_reactive$y = y
    print("End of observeEvent")
  )   # end of main_calc

  #----------------------------------------------------------------------
  # The user should be able to save the output of main_calc as a csv file
  # using a string s/he specified for the file name:
  #----------------------------------------------------------------------

  output$file_down <- downloadHandler(
    filename = function() 
      paste0(input$user_filename, " ", Sys.Date(), ".csv") 
    ,
    content = function(file) 
      print("Europe Flag is:")
      print(Data()$europe)

      if (Data()$europe == 1) 
        y_out <- forout_reactive$y
        print("Dimensions of y in downloadHandler are:")
        print(dim(y_out))        
        write.csv2(y_out, 
                   file,
                   row.names = FALSE)
       else 
        y_out <- forout_reactive$y
        print("Dimensions of y in downloadHandler are:")
        print(dim(y_out))
        write.csv(y_out, 
                  file,
                  row.names = FALSE)
      
    
  )


  # end of server code  

shinyApp(ui, server)

【讨论】:

以上是关于r闪亮:按下按钮时eventReactive没有反应的主要内容,如果未能解决你的问题,请参考以下文章

闪亮的 SelectInput 和 SelectizeInput

无法使用 observeEvent 和 eventReactive 更新闪亮应用程序中的输入

闪亮的R或两个输入过滤器

在 Shiny 中,提交按钮没有运行

停止功能以闪亮开始,直到按下按钮

需要 pandoc 1.12.3 或更高版本,但未找到(R 闪亮)