【发布时间】:2014-01-08 00:11:55
【问题描述】:
我正在使用 Shiny 构建一个 Web 应用程序,但我不确定如何最好地构建应用程序,因为输入取决于数据,而输出(图表)取决于基于输入的聚合数据。
我试图想出一个简单的应用程序来重现该问题。我的设置更高级,与示例无关。假设您有一条产品线并想分析销售情况。假设每天都创建一个数据集(我并不是说数据结构是最优的,但它对于说明我的问题很有用)。现在在应用程序中,从可用日期列表中选择一个日期,然后选择一个产品。日期仅限于数据可用的时间段,产品列表仅限于在所选日期实际售出的产品。然后,我们希望绘制一天中每个小时的总销售额。
我将在下面列出此类示例的一些代码,其中还创建了一些示例数据。对不起“长”代码。它有点工作,但我有一些担忧。
我的问题是:
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))
})
})
【问题讨论】:
-
关于
google group discussion来自@WinstonChang 的最后一条消息之一说上述更改已经合并到版本0.6.0中。 IIRC,实际版本是0.7.0,所以你应该可以使用它。至于第 1 点,我现在不能说,因为我需要进入我的 Shiny 环境。无论如何,您可以尝试使用cat来跟踪server.R的执行情况。 -
你能解决这个问题吗?我也有同样的问题。
标签: r shiny reactive-programming