我正在使用Shiny构建Web应用程序,由于输入取决于数据而输出(图表)取决于基于输入的汇总数据,因此我不确定如何最好地构建应用程序结构。

我试图提出一个简单的应用程序来重现该问题。我的设置更高级,与示例无关。假设您有一条产品线,并且想要分析销售。假设每天创建一个数据集(我并不是说数据结构是最佳的,但是它对于说明我的问题很有用)。现在在应用程序中,一个人从可用日期列表中选择一个日期,然后一个人选择一个产品。日期仅限于可获得数据的时间段,产品列表仅限于所选日期的实际销售产品。然后,我们希望绘制一天中每小时的总销售值(value)。

我将在下面的示例中列出一些代码,其中还会创建一些示例数据。对不起,“长”代码。这是可行的,但我有一些担忧。

我的问题是:

1)我想知道按什么顺序执行事情,尤其是在首次加载应用程序时,然后在每次输入更改时。同样,数据取决于第一输入,第二输入取决于数据。第三,计算用于图表的图表友好数据集。您可能会注意到错误已打印到控制台(并在浏览器中短暂闪烁),但是当这些值可用时,将进行更新并显示图。似乎不是最理想的。

2)当输入依赖于data/server.R时,当前的最佳实践是什么?我看到了这个https://groups.google.com/forum/?fromgroups=#!topic/shiny-discuss/JGJx5A3Ge-A,但似乎还没有实现,甚至以为帖子已经很老了。

这是两个文件的代码:

# ui.R
######

library(shiny)

shinyUI(pageWithSidebar(

  headerPanel("New Application"),

  sidebarPanel(
    htmlOutput("dateInput"),
    htmlOutput("prodInput")
  ),

  mainPanel(
    plotOutput("salesplot")
  )

))

和:
#server.R
#########

library(shiny)
library(filehash)

set.seed(1)

dates    <- format(seq(Sys.Date() - 10, Sys.Date(), "days"), "%Y-%m-%d")
products <- LETTERS
prices   <- sample(10:100, size = length(products), replace = TRUE)
names(prices) <- LETTERS

if (file.exists("exampledb")) {

  db <- dbInit("exampledb")

} else {

  dbCreate("exampledb")
  db <- dbInit("exampledb")

  for (d in dates) {
    no.sales <- sample(50:100, size = 1)
    x <- data.frame(
       product     = sample(products, size = no.sales, replace = TRUE)
      ,hour        = sample(8:20, size = no.sales, replace = TRUE)
      ,order.size  = sample(1:10, size = no.sales, replace = TRUE)
    )
    x$price <- prices[x$product]
    dbInsert(db, paste0("sales", gsub("-", "", d)), x)
  }
}


current <- reactiveValues()

shinyServer(function(input, output) {

  inputDates <- reactive({
    sort(strptime(unique(substr(names(db), 6, 13)), "%Y%m%d"))
  })

  output$dateInput <-  renderUI({ dateInput(
    inputId    = "date",
    label      = "Choose hour",
    min        = min(inputDates()),
    max        = max(inputDates()),
    format     = "yyyy-mm-dd",
    startview  = "month",
    weekstart  = 0,
    language   = "en")
  })

  inputProducts <- reactive({
    current$data <<- dbFetch(db, paste0("sales", format(input$date, "%Y%m%d")))
    sort(unique(current$data$product))
  })

  output$prodInput <- renderUI({ selectInput(
    inputId    = "product",
    label      = "Choose Product",
    choices    = inputProducts(),
    selected   = 1)
  })

  output$salesplot <- renderPlot({
    pdata <- aggregate(I(order.size*price) ~ hour,
      data = subset(current$data, product == input$product),
      FUN  = sum)
    colnames(pdata)[2] <- "value"
    plot(value ~ hour, data = pdata, xlim = c(8, 20))
  })


})

最佳答案

看起来这将是使用global.R。的好地方。在ui.R和server.R之前先读取global.R文件,因此您可以从ui和server均可访问的全局数据中提取数据。

关于R Shiny 的应用程序,其输入取决于更新的数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20681472/

10-12 18:00
查看更多