简体   繁体   English

如何为闪亮的仪表板创建基于汇总和过滤数据的折线图?

[英]How to create a line chart which is based on aggregated and filtered data for a shiny dashboard?

So I recently started experimenting with shiny and I like very much.所以我最近开始尝试闪亮的,我非常喜欢。 However, so far I had only very simple visualizations.然而,到目前为止,我只有非常简单的可视化。 Now I am trying to create a line chart which contains aggregated data (amounts=yaxis) and based on descrete values for the x-axis (YearsMon fi 201901).现在我正在尝试创建一个折线图,其中包含聚合数据(数量 = yaxis)并基于 x 轴的离散值(YearsMon fi 201901)。

So the idea is that i have a slider input where i can specify the range for the years and a filter which enables for me to filter the aggregated data for different categories.所以这个想法是我有一个滑块输入,我可以在其中指定年份的范围和一个过滤器,它使我能够过滤不同类别的聚合数据。

A sample of the data set is provided below.下面提供了数据集的示例。

 Generation Amount Rating
 [1,] "201806"   "100"  "A"   
 [2,] "201807"   "200"  "B"   
 [3,] "201808"   "300"  "A"   
 [4,] "201809"   "200"  "B"   
 [5,] "201810"   "200"  "A"   
 [6,] "201811"   "100"  "B"   
 [7,] "201812"   "130"  "A"   
 [8,] "201901"   "400"  "B"   
 [9,] "201902"   "300"  "A"   
[10,] "201903"   "200"  "B"   
[11,] "201806"   "300"  "A"   
[12,] "201807"   "100"  "B"   
[13,] "201808"   "400"  "A"   
[14,] "201809"   "320"  "B"   
[15,] "201810"   "200"  "A"   
[16,] "201811"   "90"   "B"   
[17,] "201812"   "230"  "A"   
[18,] "201901"   "430"  "B"   
[19,] "201902"   "190"  "A"   
[20,] "201903"   "320"  "B" 

So this is the following code I tryed:所以这是我尝试的以下代码:


Generation <- c(201806, 201807, 201808, 201809, 201810, 201811, 201812, 201901, 201902, 201903, 201806, 201807, 201808, 201809, 201810, 201811, 201812, 201901, 201902, 201903)
Amount <- c(100, 200, 300, 200, 200, 100, 130, 400, 300, 200, 300, 100, 400, 320, 200, 90, 230, 430, 190, 320)
Rating <- c("A", "B", "A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B" )

df1 = cbind(Generation, Amount, Rating)


ui1 <- fluidPage(
  theme = shinytheme("slate"),
                       sidebarLayout(
                         sidebarPanel(
                           sliderTextInput(inputId = "range", 
                                       label = "Choose range", 
                                       choices = Generation, 
                                       selected = range(Generation), 
                                       grid = TRUE),
                           selectInput(inputId = "rat",
                                       label = "Chose the rating",
                                       choices = unique(df1$rating))
                         ),#sidebar panel
                         mainPanel(verbatimTextOutput("graph1")
                         )# closing main panel
                       )# closing sidebarlayout
)# closing fluidpage


server1 = function(input, output) {

  #interactive range
  my_range <- reactive({
    cbind(input$range[1],input$range[2])
  })

  #create the filter
  df_final <- reactive({
    filter(df1, between(Generation,input$range[1],input$range[2])) %>% 
      select(Generation,input$rat) 
  })



  # createn the aggregation 
  df_final2 = reactive({
  df_final() %>%
    select(Generation, Rating, Amount) %>%
    group_by(Generation) %>%
    summarise(sum_amount = sum(Amount))
  })

  # plot the graph 
  output$graph1 <- renderPlot({

    req(df_fianl2())

     ggplot(df_final2(), aes(x = Generation, y = sum_amount)) +
      geom_line(aes(colour = Rating)) +
      geom_point()
    })
}

So what I would like to see is basically a line chart.所以我想看到的基本上是一个折线图。 On the x-axis the Generation (YearMon) which can be filtered with the SliderInput.在 x 轴上,可以使用 SliderInput 过滤的 Generation (YearMon)。 On the yaxis the aggregated amount since the amount repeat themself multiple times in the same year.在 yaxis 上的汇总金额,因为该金额在同一年重复多次。 So I would like to see the total for the year in order to plot it.所以我想看看今年的总数以便绘制它。 Last but not least I want to be able to see the plot for rating A and rating B.最后但并非最不重要的是,我希望能够看到评级 A 和评级 B 的情节。

Unfortunetly, I still struggle with the reactivity concept and therefore, I dont know how exactly to make it reactive in this way.不幸的是,我仍然在与反应性概念斗争,因此,我不知道如何以这种方式使其反应性。

I tryed looking up some solutions online but I found only one which I did not understand at all ( Line Chart Dashboard with Aggregated Data Points ).我尝试在网上查找一些解决方案,但我只找到了一个我根本不了解的解决方案( 带有聚合数据点的折线图仪表板)。 So any help is highly appriciated!所以任何帮助都是高度appriciated!

Taking GyD 's comment into account, here is a simple example.考虑到GyD的评论,这里有一个简单的例子。 I have simplified your code and there is still room for improvement:我已经简化了您的代码,但仍有改进的空间:

library(shiny)
library(dplyr)
library(ggplot2)
library(shinythemes)
library(shinyWidgets)

Generation <- c(201806, 201807, 201808, 201809, 201810, 201811, 201812, 201901, 201902, 201903, 201806, 201807, 201808, 201809, 201810, 201811, 201812, 201901, 201902, 201903)
Amount <- c(100, 200, 300, 200, 200, 100, 130, 400, 300, 200, 300, 100, 400, 320, 200, 90, 230, 430, 190, 320)
Rating <- c("A", "B", "A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B" )

df1 = data.frame(Generation, Amount, Rating)


ui1 <- fluidPage(
    theme = shinytheme("slate"),
    sidebarLayout(
        sidebarPanel(
            sliderTextInput(inputId = "range", 
                            label = "Choose range", 
                            choices = Generation, 
                            selected = range(Generation), 
                            grid = TRUE),
            selectInput(inputId = "rat",
                        label = "Choose the rating",
                        choices = unique(df1$Rating))
        ),#sidebar panel
        mainPanel(plotOutput("graph1")
        )# closing main panel
    )# closing sidebarlayout
)# closing fluidpage


server1 = function(input, output) {

    #interactive range
    # my_range <- reactive({
    #     cbind(input$range[1],input$range[2])
    # })

    #create the filter and aggregation
    df_final <- reactive({
        df1 %>% filter(between(Generation,input$range[1],input$range[2]), Rating == input$rat) %>% 
            group_by(Generation, Rating) %>%
            summarise(sum_amount = sum(Amount))
    })

    # plot the graph 
    output$graph1 <- renderPlot({

        req(df_final())

        ggplot(df_final(), aes(x = Generation, y = sum_amount)) +
            geom_line(aes(colour = Rating)) +
            geom_point()
    })
}

shinyApp(ui1, server1)

Update更新

For question 1 from the comment below:对于以下评论中的问题 1:

library(shiny)
library(dplyr)
library(ggplot2)
library(shinythemes)
library(shinyWidgets)

Generation <- c(201806, 201807, 201808, 201809, 201810, 201811, 201812, 201901, 201902, 201903, 201806, 201807, 201808, 201809, 201810, 201811, 201812, 201901, 201902, 201903)
Amount <- c(100, 200, 300, 200, 200, 100, 130, 400, 300, 200, 300, 100, 400, 320, 200, 90, 230, 430, 190, 320)
Rating <- c("A", "B", "A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B" )
Test <- c(1, 2, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1)

df1 = data.frame(Generation, Amount, Rating, Test)


ui1 <- fluidPage(
    theme = shinytheme("slate"),
    sidebarLayout(
        sidebarPanel(
            sliderTextInput(inputId = "range", 
                            label = "Choose range", 
                            choices = Generation, 
                            selected = range(Generation), 
                            grid = TRUE),
            selectInput(inputId = "rat",
                        label = "Choose the rating",
                        choices = unique(df1$Rating)),
            selectInput(inputId = "test",
                        label = "Choose the test",
                        choices = unique(df1$Test))
        ),#sidebar panel
        mainPanel(plotOutput("graph1")
        )# closing main panel
    )# closing sidebarlayout
)# closing fluidpage


server1 = function(input, output) {

    #interactive range
    # my_range <- reactive({
    #     cbind(input$range[1],input$range[2])
    # })

    #create the filter and aggregation
    df_final <- reactive({
        df1 %>% filter(between(Generation,input$range[1],input$range[2]), Rating == input$rat, Test == input$test) %>% 
            group_by(Generation) %>%
            summarise(sum_amount = sum(Amount))
    })

    # plot the graph 
    output$graph1 <- renderPlot({

        req(df_final())

        ggplot(df_final(), aes(x = Generation, y = sum_amount)) +
            geom_line() +
            geom_point()
    })
}

shinyApp(ui1, server1)

Notice how I added a Test column to df1 and both Rating and Test are in filter but not group_by.请注意我如何向 df1 添加一个 Test 列,并且 Rating 和 Test 都在过滤器中但不是 group_by。

For question 2 from the comment below:对于下面评论中的问题2:

library(shiny)
library(dplyr)
library(ggplot2)
library(shinythemes)
library(shinyWidgets)

Generation <- c(201806, 201807, 201808, 201809, 201810, 201811, 201812, 201901, 201902, 201903, 201806, 201807, 201808, 201809, 201810, 201811, 201812, 201901, 201902, 201903)
Amount <- c(100, 200, 300, 200, 200, 100, 130, 400, 300, 200, 300, 100, 400, 320, 200, 90, 230, 430, 190, 320)
Rating <- c("A", "B", "A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B","A", "B" )

df1 = data.frame(Generation, Amount, Rating)


ui1 <- fluidPage(
    theme = shinytheme("slate"),
    sidebarLayout(
        sidebarPanel(
            sliderTextInput(inputId = "range", 
                            label = "Choose range", 
                            choices = Generation, 
                            selected = range(Generation), 
                            grid = TRUE),
            selectInput(inputId = "rat",
                        label = "Choose the rating",
                        choices = c("A", "B", "A & B - one line", "A & B - two lines"))
        ),#sidebar panel
        mainPanel(plotOutput("graph1")
        )# closing main panel
    )# closing sidebarlayout
)# closing fluidpage


server1 = function(input, output) {

    #interactive range
    # my_range <- reactive({
    #     cbind(input$range[1],input$range[2])
    # })

    #create the filter and aggregation
    df_final <- reactive({
        if(input$rat %in% c("A", "B")) {
            df1 %>% filter(between(Generation,input$range[1],input$range[2]), Rating == input$rat) %>% 
                group_by(Generation) %>%
                summarise(sum_amount = sum(Amount))
        }else if(input$rat == "A & B - one line"){
            df1 %>% filter(between(Generation,input$range[1],input$range[2])) %>% 
                group_by(Generation) %>%
                summarise(sum_amount = sum(Amount))
        }else if(input$rat == "A & B - two lines"){ # this if isn't necessary but included for clarity
            df1 %>% filter(between(Generation,input$range[1],input$range[2])) %>% 
                group_by(Generation, Rating) %>%
                summarise(sum_amount = sum(Amount))
        }

    })

    # plot the graph 
    output$graph1 <- renderPlot({

        req(df_final())
        if(input$rat != "A & B - two lines"){
            ggplot(df_final(), aes(x = Generation, y = sum_amount)) +
                geom_line() +
                geom_point()
        }else{
            ggplot(df_final(), aes(x = Generation, y = sum_amount)) +
                geom_line(aes(colour = Rating)) +
                geom_point()
        }

    })
}

shinyApp(ui1, server1)

Notice how only the two lines option needs a colour parameter.请注意只有两行选项需要颜色参数。 Basically, the selectInput or radioButton just indicates the selection in the ui (you can rename these as you desire), the real work happens in the server.基本上, selectInput 或 radioButton 只是指示 ui 中的选择(您可以根据需要重命名它们),真正的工作发生在服务器中。 Again, I'm sure there are other ways of doing this but if you master the tidyverse functions you'll be able to manipulate the data as you wish.同样,我确信还有其他方法可以做到这一点,但如果您掌握了 tidyverse 函数,您将能够按照自己的意愿操作数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM