在我的shinyApp服务器中,我根据输入创建了一个数据帧。但是,我想添加一个新列,该列使用该数据帧的两列。
server <- function(input, output, session) {
l.out <- reactive({
BatchGetSymbols(tickers = input$stock,
first.date = Sys.Date() - as.integer(input$length),
last.date = Sys.Date())
})
stock_info <- reactive({
l.out()$df.tickers
})
stock_info()$return <- reactive({
rep(0, length(stock_info()$ref.date))
})
stock_info()$return <- reactive({
for (i in 2:length(stock_info()$ref.date)){
stock_info()$return[i] <- ((stock_info()$price.close[i] -
stock_info()$price.close[i - 1]) / stock_info$price.close[i - 1])
}
})
我已经尝试过这样做,直到我尝试创建stock_info()$ return,然后我不断收到NULL留下的错误。 有什么提示吗?
答案 0 :(得分:0)
我不熟悉BatchGetSymbols
包,但下面示例中的概念也适用于您的用例。
首先,由于缺乏优雅的说法,我非常肯定这个表达......
stock_info()$return <- reactive({
rep(0, length(stock_info()$ref.date))
})
...实际上并不是shiny
反应对象和相关语法的工作方式。
看起来你可以通过将一堆中间步骤压缩成单个表达式来简化代码。如果您只有一组反应数据,您将在所有输出中使用,这可能是一种更直接的方法。
library(shiny)
ui <- fluidPage(
textInput('stock','stock',"GE"),
sliderInput('length', 'length', min = 1, max = 10, value = 5),
dataTableOutput('my_table')
)
server <- function(input, output, session) {
## This will update whenever either input$length or input$stock change
stock_info <- reactive({
length <- as.integer(input$length)
temp_stock_info <- data.frame(stock = input$stock,
foo = seq_len(length),
bar = rnorm(length))
temp_stock_info$baz <- paste("xxx",length)
return(temp_stock_info)
})
## Return an output
output$my_table <- renderDataTable({
stock_info()
})
}
shinyApp(ui, server)
但是,如果您将中间对象l.out
用于各种结束输出,那么将它作为自己的反应对象可能是有意义的。然后,只要相关输入发生变化,我们就可以更新l.out
,然后使用该中间变量通过其他下游反应来级联更新。
此外,我们可以根据不会影响stock_info
的其他条件更新下游的被动对象,例如l.out
,而不必每次都重新运行l.out
。
library(shiny)
ui <- fluidPage(
textInput('stock','stock',"GE"),
sliderInput('length', 'length', min = 1, max = 100, value = 50),
sliderInput('displayLength', 'displayLength', min = 1, max = 20, value = 5),
dataTableOutput('my_table')
)
server <- function(input, output, session) {
## l.out will change with input$length and input$stock
## but NOT input$displayLength
l.out <- reactive({
data.frame(stock = input$stock,
foo = rnorm(input$length),
l.out_update_time = Sys.time())
})
## stock_info will update whenever l.out changes or the displayLength changes.
## l.out will NOT be updated if only input$displayLength changes
stock_info <- reactive({
tmp_stock_info <- head(x = l.out(), n = input$displayLength)
tmp_stock_info$stock_info_update_time <- Sys.time()
return(tmp_stock_info)
})
## Return an output
output$my_table <- renderDataTable({
stock_info()
})
}
shinyApp(ui, server)