优化性能 - Shiny 中的大文件输入
Optimizing Performance - Large File Input in Shiny
我在文件 CheckClawback.R 中定义了一个函数 (clawCheck),它将三个数据帧作为参数。在我的 Shiny 应用程序中,用户上传三个文件,然后将其读入内存并用作 ClawCheck 参数。为了节省时间,我希望 R 在文件上传后立即开始将文件读入内存,而不是仅在按下 "GO" 按钮之后,以便一旦按下按钮,ClawCheck 的参数是已在内存中并可以使用。
我想我必须在 renderTable 语句中使用 eventReactive 表达式,因为我不希望每次用户更改某些输入时都重新读取文件。为了避免进一步复杂化,我假设输入是按顺序填写的,即首先 "account",然后 "commpaid",然后 "termriders"。当我 运行 应用程序和第一个输入文件已上传时,没有出现进度条,这表明我的代码无法正常工作。这是我的(简化的)代码:
library('shiny')
source("CheckClawback.R")
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("account", "Account File (.csv)"),
fileInput("commpaid", "CommPaid File (.txt)"),
fileInput("termriders", "TermRiders File (.txt)"),
actionButton("do", "GO!")),
mainPanel(
tableOutput("out_table"))
)
)
server <- function(input, output) {
func <- eventReactive(input$do, {
req(acc)
req(comm)
req(term)
datat <<- clawCheck(acc, comm, term)
})
output$out_table <- renderTable({
eventReactive(input$account, {
withProgress(message = "Preparing Account Data...Please Wait", {
acc <<- read.csv(input$account$datapath, header = TRUE, sep = ",")
})
})
eventReactive(input$commpaid, {
withProgress(message = "Preparing CommPaid Data...Please Wait", {
comm <<- read.table(input$commpaid$datapath, header = TRUE, sep = "\t")
})
})
eventReactive(input$termriders, {
withProgress(message = "Preparing TermRiders Data...Please Wait", {
term <<- read.table(input$termriders$datapath, header = TRUE, sep = "\t")
})
})
withProgress(func(), message = "Loading Output...Please Wait")
datat
})
}
shinyApp(ui = ui, server = server)
理想情况下,文件上传后,应该出现一个进度条,表示正在处理中。如果在此过程中上传了第二个文件,则应出现第二个进度条,表明正在处理第二个文件等。一旦实际函数调用发生,我希望输入文件准备就绪。
非常感谢您的帮助!
您对 <<-
和 withProgress()
的使用是错误的。此外,在 render*()
中使用 eventReactive()
是错误的。我建议阅读 RStudio Shiny 教程,以帮助理解 reactivity 的工作原理。另请查看 showNotification()
而不是 withProgress()
。现在,这就是您可能需要的 -
server <- function(input, output, session) {
acc <- reactive({
validate(need(input$account), "acc not uploaded")
# use showNotification(); use same approach for other files
read.csv(input$account$datapath, header = TRUE, sep = ",")
# use removeNotification() to remove mesg after file is uploaded
})
comm <- reactive({
validate(need(input$commpaid), "comm not uploaded")
read.table(input$commpaid$datapath, header = TRUE, sep = "\t")
})
term <- reactive({
validate(need(input$termriders), "term not uploaded")
read.table(input$termriders$datapath, header = TRUE, sep = "\t")
})
func <- eventReactive(input$do, {
clawCheck(acc(), comm(), term())
})
output$out_table <- renderTable({
func()
})
}
我在文件 CheckClawback.R 中定义了一个函数 (clawCheck),它将三个数据帧作为参数。在我的 Shiny 应用程序中,用户上传三个文件,然后将其读入内存并用作 ClawCheck 参数。为了节省时间,我希望 R 在文件上传后立即开始将文件读入内存,而不是仅在按下 "GO" 按钮之后,以便一旦按下按钮,ClawCheck 的参数是已在内存中并可以使用。
我想我必须在 renderTable 语句中使用 eventReactive 表达式,因为我不希望每次用户更改某些输入时都重新读取文件。为了避免进一步复杂化,我假设输入是按顺序填写的,即首先 "account",然后 "commpaid",然后 "termriders"。当我 运行 应用程序和第一个输入文件已上传时,没有出现进度条,这表明我的代码无法正常工作。这是我的(简化的)代码:
library('shiny')
source("CheckClawback.R")
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("account", "Account File (.csv)"),
fileInput("commpaid", "CommPaid File (.txt)"),
fileInput("termriders", "TermRiders File (.txt)"),
actionButton("do", "GO!")),
mainPanel(
tableOutput("out_table"))
)
)
server <- function(input, output) {
func <- eventReactive(input$do, {
req(acc)
req(comm)
req(term)
datat <<- clawCheck(acc, comm, term)
})
output$out_table <- renderTable({
eventReactive(input$account, {
withProgress(message = "Preparing Account Data...Please Wait", {
acc <<- read.csv(input$account$datapath, header = TRUE, sep = ",")
})
})
eventReactive(input$commpaid, {
withProgress(message = "Preparing CommPaid Data...Please Wait", {
comm <<- read.table(input$commpaid$datapath, header = TRUE, sep = "\t")
})
})
eventReactive(input$termriders, {
withProgress(message = "Preparing TermRiders Data...Please Wait", {
term <<- read.table(input$termriders$datapath, header = TRUE, sep = "\t")
})
})
withProgress(func(), message = "Loading Output...Please Wait")
datat
})
}
shinyApp(ui = ui, server = server)
理想情况下,文件上传后,应该出现一个进度条,表示正在处理中。如果在此过程中上传了第二个文件,则应出现第二个进度条,表明正在处理第二个文件等。一旦实际函数调用发生,我希望输入文件准备就绪。
非常感谢您的帮助!
您对 <<-
和 withProgress()
的使用是错误的。此外,在 render*()
中使用 eventReactive()
是错误的。我建议阅读 RStudio Shiny 教程,以帮助理解 reactivity 的工作原理。另请查看 showNotification()
而不是 withProgress()
。现在,这就是您可能需要的 -
server <- function(input, output, session) {
acc <- reactive({
validate(need(input$account), "acc not uploaded")
# use showNotification(); use same approach for other files
read.csv(input$account$datapath, header = TRUE, sep = ",")
# use removeNotification() to remove mesg after file is uploaded
})
comm <- reactive({
validate(need(input$commpaid), "comm not uploaded")
read.table(input$commpaid$datapath, header = TRUE, sep = "\t")
})
term <- reactive({
validate(need(input$termriders), "term not uploaded")
read.table(input$termriders$datapath, header = TRUE, sep = "\t")
})
func <- eventReactive(input$do, {
clawCheck(acc(), comm(), term())
})
output$out_table <- renderTable({
func()
})
}