r shiny:按下按钮时eventReactive没有反应

时间:2018-02-21 16:10:55

标签: r shiny reactive

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

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

我的问题:上传文件后,当我点击' do_it'动作按钮 - 没有任何反应。我可以看到它,因为我的控制台上没有打印任何内容。为什么?毕竟,我的功能' main_calc'应该是eventReactive来输入$ 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)

1 个答案:

答案 0 :(得分: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)