对于我的工作,我正在创建一个闪亮的应用程序。它目前工作正常,但获取数据需要我与SQL接口,这需要一段时间。此应用程序以两种方式使用数据:1)显示数据,2)使用数据运行模拟(这也很耗时)。我需要能够为许多不同的客户获取数据。
到目前为止,我可以将数据与模拟分开,并使用我已经在模拟中直接获得的数据,前提是我已经拥有了正确的数据。如果客户编号发生变化,我可以获取数据并运行模拟。所有这些都很棒,但我不能做的一件事就是显示我得到的数据用于模拟,如果我还没有正确的数据。
我已经尝试了几种方法来实现这一目标,但我正在研究的那个方法是尝试让数据对象保持原样,如果我已经拥有数据,并且客户编号是正确的,但是在所有其他情况。我试图做的所有方法都给了我一个无限循环或空白数据集。我创建了一个愚蠢的应用程序版本(因为我无法显示真正的应用程序),应该突出我遇到的问题。这就是我目前所拥有的:
library(shiny)
shinyUI(fluidPage(
fluidRow(wellPanel(
#create at action button to generate data.
actionButton("gen", "Generate"),
textOutput("check")
),
wellPanel(
#'create an action button for simulation. Here there is no simulation because
#'I am not having a problem with simulation, but this should also generate
#'data if there is no data, or the customer numbers do not match
actionButton("sim", "Simulate"),
#indicates whether the customer numbers match
checkboxInput("same", "Same customer number", value = T),
#output the data table
dataTableOutput("data")
))
))
library(mvtnorm)
shinyServer(function(input, output){
#'every time I hit the sim button, this is set as the gen button's count.
#'By checking to see if this equals the count of the gen button, I can generate
#'data every time I hit the gen button, but not every time I hit the sim button
gen.check<-reactive({
input$sim
isolate({as.numeric(input$gen)})
})
output$check<-renderText({
gen.check()<input$gen
})
#indicates whether there is already data or not
check<-reactive({
if(input$gen==0 & input$sim==0){
FALSE
}else{
TRUE
}
})
#generate the data
data<-reactive({
#'this stops the app from displaying data when it opens. Not super important
#'here, but in the actual app, getting the data is time consuming, so I don't
#'want it to start out by getting data I don't need
if(input$gen==0 & input$sim==0){
return()
}
#This line makes data show up every time I hit the gen button
if(input$gen>gen.check()){
rmvnorm(20, 1:5, diag(5))
}else{
#'I had hoped this blank loop here would make the data stay the same if there
#'already was data, and the customer numbers matched, but instead it makes the
#'data disappear under these conditions
if(isolate({input$same}) & check()){
}else{
#'This generates data if there is none, or if the numbers don't match when
#'you hit sim
rmvnorm(200, 1:5, diag(rep(.1, 5)))
}
}
})
#'This piece is separate because in the actual app I need to use the data generated
#'above two different ways. I am just using it here to check when the data changes.
output$data<-renderDataTable({
if(input$gen==0 & input$sim==0){
return()
}
as.data.frame(data())
})
})
当我单击“gen”按钮时,代码成功生成数据。当我单击“sim”按钮时,如果复选框指示数字不相同,它还会生成并显示数据。我希望如果我已经生成了数据,并且我点击了模拟,那么如果客户编号是相同的,那么我所显示的数据就不会发生。
我在这里直接显示的数据()将在我为工作创建的应用程序中使用相同的方式(尽管它将是真实数据,而不是生成的数据),并且相同的数据()直接转到模拟。只有在适当的时候才能改变这一点,这是我遇到的唯一问题。
编辑:这是我第一次提出问题,所以我确信我的格式很差。如果仍不清楚,请尽量让我知道我在哪里失去你。
编辑:memoise包能够完成任务。例如,如果我的数据抓取功能是data.grab(customer_no),并且需要与SQL接口,那么在我的应用程序之前,我包括
grabber<-memoise(data.grab)
然后我用抓取器替换了data.grab的所有实例。如果我使用我之前使用的相同客户,它会使用上次使用这些参数运行函数的结果,而不是再次与SQL连接。