闪亮的应用程序 - 多种用途的反应数据框架&延迟活动

时间:2018-02-16 11:53:39

标签: r shiny

我正在创建一个包含多个KPI值框的闪亮仪表板。我不会粘贴整个服务器/代码(> 500行代码),但每个框都使用renderValueBox调用,我创建数据框“kpidat”使用(我为每个框执行此操作),我使用if用于确定框的颜色和符号的语句。请参阅下面的示例代码:

output$incbox <- renderValueBox({

    area_prev<-as.character(input$dynamic2)
    prev_region<-input$select_B
    kpidat<-sept[sept$area==area_prev & sept$region==prev_region,]

    if(kpidat$`New TB incidents`[2]>kpidat$`New TB incidents`[1]){a<-"arrow-up";b<-"red"}
    if(kpidat$`New TB incidents`[2]<kpidat$`New TB incidents`[1]){a<-"arrow-down";b<-"green"}
    if(kpidat$`New TB incidents`[2]==kpidat$`New TB incidents`[1]){a<-"";b<-"yellow"}

    valueBox(
        paste0(kpidat$`New TB incidents`[2], "Incidents"), "Number of disease incidents.", 

        icon = icon(a),
        color = b
    )
})

代码工作正常,但我有两个问题:

  1. 如何创建单个数据框,然后由多个后续函数(renderPlot,renderValueBox等)使用而不会一次又一次地创建kpidat?我假设使用reactive(),但我找不到任何相关的例子或想出来。

  2. 在绘制值框之前有一个短暂的延迟...在此期间可以看到错误消息(我认为这是因为kpidat在一秒左右不可用)。在相关数据可用之前,如何延迟绘制数值框?如果样式语句没有成功,我已经尝试了一系列req()。

  3. 任何帮助都会非常感激。

    安迪

1 个答案:

答案 0 :(得分:0)

一些建议:

  • 您可以将kpidat定义为响应对象,只要input$select_B更改,它就会更新。要在其他输出中使用它,请使用kpidat()进行调用。即使您在多个其他输出中使用它,kpidat <- reactive({...})中的表达式也只会执行一次。

  • 通过将输出计算包装在tryCatch()语句中,如果在呈现实际输出的过程中发生任何错误,则可以返回空valueBox(Good explanation of tryCatch here)这样可以保护用户免受丑陋的错误消息的影响,同时仍然可以返回占位符。

  • 在可能的情况下,高效编程仍然是加速的最佳机会。而不是像local_kpidat$'New TB incidents'[2]那样评估子集3次,只需执行一次并将其分配给临时变量。

kpidat <- reactive({
  return(sept[sept$area==as.character(input$dynamic2) & sept$region==input$select_B,])
})

output$incbox <- renderValueBox({
  tryCatch({
    ## This will return if it can execute successfully
    local_kpidat <- kpidat()

    ## Only calculate these once
    foo <- local_kpidat$`New TB incidents`[2]
    bar <- local_kpidat$`New TB incidents`[1]

    if(foo >  bar){a<-"arrow-up";b<-"red"}
    if(foo <  bar){a<-"arrow-down";b<-"green"}
    if(foo == bar){a<-"";b<-"yellow"}

    valueBox(value = paste0(kpidat$`New TB incidents`[2], "Incidents"),
             subtitle = "Number of disease incidents.",
             icon = icon(a),
             color = b)

  }, error = function(e) {
    ## This, an empty value box, will be returned if any errors occur
    valueBox(value = "","")
  })
})

如果滞后时间存在问题,您可能需要考虑从使用data.frame切换到data.table(来自data.table包)。对于后端具有足够大数据集的Web应用程序,子集化的执行速度越快,就会产生很大的差异。 (如果您在sept处理&lt; 1000行,这可能不会产生巨大影响)

我没有看到您在这里推测的数据,但似乎可以使用data.table的{​​{1}}并按分组来分配shift和{{1}在启动时一次a内的列。每次用户更改输入时,这可能会大大减少更新时间。

以下示例是大修可能如何发挥作用。

无论何时加载包

,都会在服务器代码之外执行
b

这将在您的服务器中正常

sept