在shiny/shiny dashboard R中为响应式数据框创建新列

4

在我的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 left assignment错误。有什么提示吗?


2
请查看如何创建一个好的Shiny可重现示例?,如果您可以根据这些建议更新您的示例,那将有助于其他人帮助您! - Matt Summersgill
如果这样更容易的话,我可以发布完整的代码。显然,UI代码和很多多余的服务器代码都不适用,但它会更好地理解整个情况。 - Liam Hash
您最初的直觉是正确的,发布完整代码会使信息变得混乱。示例代码应包括加载使用的任何包 - library(shiny)library(BatchGetSymbols)等。示例ui应只包括 input$stockinput$length(具有工作默认值) 和表格输出打印所需结果数据框stock_info。你已经有了足够的示例server代码_(即使它不起作用)_。这里是可能看起来像什么的 gist - Matt Summersgill
1个回答

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,然后使用该中间变量通过其他下游反应性级联更新。

此外,我们可以根据不影响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)

BatchGetSymbols包从互联网获取大量股票信息,然后将其存储为其自己的数据帧集合,这就是为什么我需要在获取l.out() $ df.tickers之前将其存储为l.out的原因,后者是包含最相关股票信息(收盘价等)的数据框。基本上,一旦我拥有了l.out和stock_info <- l.out()$df.tickers,我正在尝试创建一种简单的方法来添加一个列而不编辑整个数据框(基本上有一个输入只需要这个额外的列,即股票回报)。如果有用的话,我可以发布代码的其余部分。 - Liam Hash
每当我按照BatchGetSymbols vignette中的示例运行时,都只会收到错误消息。如果您能提供一个包含硬编码输入的可工作的BatchGetSymbols()调用,那将非常有帮助。 - Matt Summersgill
库(批量获取符号)#设置日期 first.date <- Sys.Date() - 365 last.date <- Sys.Date()#设置股票代码tickers <- c("PYPL")l.out <- BatchGetSymbols(tickers = tickers, first.date = first.date, last.date = last.date ) 这是该软件包通常的工作方式,其中l.out $ df.tickers具有最重要的股票信息。 我的闪亮应用程序的代码非常广泛,因为它有很多部分。 有没有可能我可以向您发送代码以获得帮助? - Liam Hash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接