【问题标题】:Shiny: calculate cumsum based on dygraphs' RangeSelectorShiny:根据 dygraphs 的 RangeSelector 计算 cumsum
【发布时间】:2019-04-25 16:43:33
【问题描述】:

我正在构建一个闪亮的应用程序,我想在其中绘制一个数据集,其中一个变量是另一个变量的累积和。每次dygraphs'dyRangeSelector的开始日期发生变化时,都需要重新计算后者。下面是没有cumsum 计算的基本代码。注释掉的代码是我尝试过的,但没有成功。

library(shinydashboard)
library(stringr)
library(zoo)
library(dplyr)
library(dygraphs)

ui <-dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    uiOutput("Ui1")
  )
)

server <- function(input, output, session) {


  output$Ui1 <- renderUI({

    # date range observer 

    # values <- reactiveValues()
    # 
    # observeEvent(input$plot1_date_window, {
    #   from <- as.Date(str_sub(input$plot1_date_window[[1]], 1, 10))
    # })

    ## dygraphs plot 
    output$plot1 <- renderDygraph({

      m_df <- data.frame(date=as.Date(zoo::as.yearmon(time(mdeaths))), Y=as.matrix(mdeaths))

      # input_data <- m_df %>% 
      #   filter(date >= values$from) %>% 
      #   mutate(cumY = cumsum(Y)) 

      input_xts <- xts(select(m_df, -date), 
                       order.by = m_df$date)
                       #select(input_data, -date),
                       #order.by = input_data$date)


      p <- dygraph(input_xts) %>% 
        dyRangeSelector()

      p  
    })

    ## outputs
    dygraphOutput('plot1')
  })


}

shinyApp(ui, server)

更新

我修改了@Pork Chop 的答案,以便能够在一张图上绘制具有其他指标的累积值,但我现在什至无法显示该图:

library(xts)
library(shiny)
library(shinydashboard)
library(dygraphs)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    dygraphOutput('plot1'),
    textOutput("cumsum1")
  )
)

server <- function(input, output, session) {

  m_df <- data.frame(date=as.Date(zoo::as.yearmon(time(mdeaths))), Y=as.matrix(mdeaths))
  subdata <- reactive({
    cumsum(m_df$Y[m_df$date >= as.Date(input$plot1_date_window[1]) & m_df$date <= as.Date(input$plot1_date_window[2])])
  })

  output$plot1 <- renderDygraph({
    req(input$plot1_date_window)
    input_xts <- xts(select(m_df, -date), order.by = m_df$date)
    subdata_xts <- xts(select(subdata(), - date), order.by = subdata()$date)
    final_xts <- cbind(input_xts, subdata_xts)

    dygraph(final_xts) %>% 
      dyRangeSelector()
  })

  output$cumsum1 <- renderText({
    req(input$plot1_date_window)
    subdata <- cumsum(m_df$Y[m_df$date >= as.Date(input$plot1_date_window[1]) & m_df$date <= as.Date(input$plot1_date_window[2])])
    subdata
  })

}

shinyApp(ui, server)

【问题讨论】:

    标签: shiny shinydashboard dygraphs cumsum


    【解决方案1】:

    更新代码的问题在于,您没有保留日期信息。此外,一旦您开始根据情节本身的变化(递归)来渲染情节,它就会变得有点棘手。您必须确保重新渲染绘图不会再次触发渲染,否则您将陷入循环。这就是我设置retainDateWindow = TRUE 的原因。除此之外,您不希望在第一次更改滑块后立即重新渲染绘图,这就是我对子数据进行去抖动的原因。

    尽管如此,使用 dygraphs 仍然存在问题,当您将 cumsum 添加为系列时,您的 dyRangeSelector 情节会发生变化(所有系列中的最大值)。请看以下代码:

    library(xts)
    library(shiny)
    library(shinydashboard)
    library(dygraphs)
    library(dplyr)
    
    ui <- dashboardPage(
      dashboardHeader(),
      dashboardSidebar(),
      dashboardBody(
        dygraphOutput('plot1')
      )
    )
    
    server <- function(input, output, session) {
    
      m_df <- data.frame(date=as.Date(zoo::as.yearmon(time(mdeaths))), Y=as.matrix(mdeaths))
    
      subdata <- reactive({
        if(!is.null(input$plot1_date_window)){
          subdata <- m_df[m_df$date >= as.Date(input$plot1_date_window[1]) & m_df$date <= as.Date(input$plot1_date_window[2]), ]
          subdata$cumsum <- cumsum(subdata$Y)
          subdata$Y <- NULL
        } else {
          subdata <- NULL
        }
    
        return(subdata)
      })
    
      subdata_d <- subdata %>% debounce(100)
    
      output$plot1 <- renderDygraph({
        input_xts <- xts(select(m_df, -date), order.by = m_df$date)
        if(is.null(subdata_d())){
          final_xts <- input_xts
        } else {
    
          subdata_xts <- xts(select(subdata_d(), - date), order.by = subdata_d()$date)
          final_xts <- cbind(input_xts, subdata_xts)
        }
    
        p <- dygraph(final_xts) %>% dySeries(name="Y") %>%
          dyRangeSelector(retainDateWindow = TRUE)
    
        if("cumsum" %in% names(final_xts)){
          p <- dySeries(p, name="cumsum", axis = "y2")
        }
    
        p
      })
    
    }
    
    shinyApp(ui, server)
    

    正如@PorkChop 提到的那样,我会为这种情况推荐多个输出。此外,我建议您查看library(plotly),它是event_data()

    【讨论】:

      【解决方案2】:

      这应该可以完成这项工作,我认为为仪表板提供单独的输出会更干净

      library(xts)
      library(shiny)
      library(shinydashboard)
      library(dygraphs)
      
      ui <- dashboardPage(
        dashboardHeader(),
        dashboardSidebar(),
        dashboardBody(
          dygraphOutput('plot1'),
          textOutput("cumsum1")
        )
      )
      
      server <- function(input, output, session) {
      
        m_df <- data.frame(date=as.Date(zoo::as.yearmon(time(mdeaths))), Y=as.matrix(mdeaths))
      
        output$plot1 <- renderDygraph({
          input_xts <- xts(select(m_df, -date), order.by = m_df$date)
      
          dygraph(input_xts) %>% 
            dyRangeSelector()
        })
      
        output$cumsum1 <- renderText({
          req(input$plot1_date_window)
          subdata <- cumsum(m_df$Y[m_df$date >= as.Date(input$plot1_date_window[1]) & m_df$date <= as.Date(input$plot1_date_window[2])])
          subdata
        })
      
      }
      
      shinyApp(ui, server)
      

      【讨论】:

      • 谢谢,这是一个很好的开始,但我需要能够将这些累积值与来自同一数据集的其他指标一起绘制在一个图表上。我修改了您的答案(请参阅我更新的问题),但仍然收效甚微。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-29
      • 1970-01-01
      • 2013-05-26
      • 2016-06-26
      • 2018-06-26
      • 1970-01-01
      相关资源
      最近更新 更多