我正在创建一个包含多个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
)
})
代码工作正常,但我有两个问题:
如何创建单个数据框,然后由多个后续函数(renderPlot,renderValueBox等)使用而不会一次又一次地创建kpidat?我假设使用reactive()
,但我找不到任何相关的例子或想出来。
在绘制值框之前有一个短暂的延迟...在此期间可以看到错误消息(我认为这是因为kpidat在一秒左右不可用)。在相关数据可用之前,如何延迟绘制数值框?如果样式语句没有成功,我已经尝试了一系列req()。
任何帮助都会非常感激。
安迪
答案 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