График Ggplot2 в R Shiny с линией в соответствии с пользовательским вводом - PullRequest
1 голос
/ 09 января 2020

Я хочу построить график в моем приложении Shiny, используя ggplot2, который строит линию, касающуюся выбора пользователя, по topi c. В этом вопросе Мне сказали, как добавить эти 0 в случае, если у данного топи c нет элемента (используя ответ ankrun). Сейчас я ищу вписать этот график в блестящее приложение и подумал о добавлении sliderInput, где вы можете выбрать topi c для линии. Вот что я попробовал:

# # # global # # #
#1. App
if("shiny" %in% rownames(installed.packages()) == FALSE){ install.packages("shiny") }
library(shiny)
#2. Easier data handling
if("dplyr" %in% rownames(installed.packages()) == FALSE){ install.packages("dplyr") }
library(dplyr)
#3. Graphs
if("ggplot2" %in% rownames(installed.packages()) == FALSE){ install.packages("ggplot2") }
library(ggplot2)
#4. Completion in graphs
if("tidyr" %in% rownames(installed.packages()) == FALSE){ install.packages("tidyr") }
library(tidyr)

# # # ui # # #
ui <- fluidPage( 
  sidebarPanel(
    selectInput("select_topic_timeline", "What topic?",
                choices = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"), 
                selected =  c("1", "2", "3", "4","5", "6", "7", "8", "9", "10", "11", "12"),
                multiple = T)
  ),#sidebarPanel
  mainPanel( 
    plotOutput("per_topic_timeline")
  ) #mainPanel
) #fluidPage

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

  # TIMELINE PER TOPIC PER YEAR
  output$per_topic_timeline <- renderPlot({
  dtd2 <- structure(list(Topic = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                                             1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
                                             3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 
                                             5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 
                                             7L, 7L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 
                                             10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 
                                             11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 12L), .Label = c("Topic 1", 
                                                                                                                     "Topic 10", "Topic 11", "Topic 12", "Topic 2", "Topic 3", "Topic 4", 
                                                                                                                     "Topic 5", "Topic 6", "Topic 7", "Topic 8", "Topic 9"), class = "factor"), 
                         Year = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 2L, 
                                            3L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 
                                            3L, 4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 
                                            9L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 
                                            8L, 9L, 1L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 6L, 7L, 8L, 
                                            9L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L, 4L, 5L, 
                                            6L, 7L, 8L, 9L, 2L, 3L, 4L, 5L, 6L, 7L, 8L), .Label = c("2011", 
                                                                                                    "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019"
                                            ), class = "factor"), Count = c(3L, 3L, 3L, 5L, 5L, 11L, 
                                                                            17L, 14L, 4L, 1L, 1L, 4L, 2L, 3L, 9L, 4L, 2L, 1L, 3L, 4L, 
                                                                            5L, 18L, 23L, 19L, 15L, 1L, 5L, 6L, 8L, 11L, 17L, 7L, 1L, 
                                                                            3L, 6L, 4L, 20L, 21L, 18L, 12L, 3L, 1L, 1L, 2L, 5L, 5L, 11L, 
                                                                            5L, 2L, 1L, 1L, 2L, 2L, 5L, 7L, 23L, 9L, 1L, 1L, 2L, 3L, 
                                                                            6L, 4L, 9L, 8L, 1L, 1L, 6L, 2L, 3L, 3L, 1L, 3L, 2L, 5L, 7L, 
                                                                            11L, 11L, 28L, 11L, 2L, 1L, 2L, 2L, 5L, 6L, 5L, 16L, 3L, 
                                                                            4L, 2L, 2L, 7L, 6L, 8L, 6L)), row.names = c(NA, -96L), class = "data.frame")

  dtd2 %>%
      expand(Topic = factor(Topic, levels = gtools::mixedsort(levels(c(input$select_topic_timeline)))) ,
             Year = unique(Year)) %>% 
      left_join(dtd2) %>% 
      mutate(Count = replace_na(Count, 0)) %>%
      ggplot(aes(x = Year, y = Count), colour = c(input$select_topic_timeline), group = Topic) + 
      geom_point() +
      geom_line() +
      labs(x = "Year", y = NULL, title = "Timeline")
  })
}

shinyApp(ui,server)

Он не печатает никаких ошибок, но говорит Warning: Column "Topic" joining factors with different levels, coercing to character vector и не выдает никакого графика, только пустое серое поле. Я не уверен, как вписать ввод в код графика, и я, должно быть, изменил его неправильно!

1 Ответ

1 голос
/ 09 января 2020

Эта проблема заключается в том, что вы в основном рефакторинге dtd2$Topic на основе того, что в selectInput, но поскольку Topic имеет только 9 уровней, и вы можете выбрать до 12 уровней с помощью selectInput, вы получение ошибок.

По этой причине я бы предложил вместо этого использовать ответ @Ronak Shah с tidyr::complete.

После того, как вы completed данных, вам следует dplyr::filter по Topi c, чтобы получить желаемый результат:

# # # global # # #
#1. App
if("shiny" %in% rownames(installed.packages()) == FALSE){ install.packages("shiny") }
library(shiny)
#2. Easier data handling
if("dplyr" %in% rownames(installed.packages()) == FALSE){ install.packages("dplyr") }
library(dplyr)
#3. Graphs
if("ggplot2" %in% rownames(installed.packages()) == FALSE){ install.packages("ggplot2") }
library(ggplot2)
#4. Completion in graphs
if("tidyr" %in% rownames(installed.packages()) == FALSE){ install.packages("tidyr") }
library(tidyr)

# # # ui # # #
ui <- fluidPage( 
  sidebarPanel(
    selectInput("select_topic_timeline", 
                label = "What topic?",
                choices = as.character(1:12), 
                selected = as.character(1:12),
                multiple = TRUE),
  ),#sidebarPanel
  mainPanel( 
    plotOutput("per_topic_timeline")
  ) #mainPanel
) #fluidPage

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

  # TIMELINE PER TOPIC PER YEAR
  output$per_topic_timeline <- renderPlot({
    dtd2 <- structure(list(Topic = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                                               1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
                                               3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 
                                               5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 
                                               7L, 7L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 
                                               10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 
                                               11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 12L), .Label = c("Topic 1", 
                                                                                                                       "Topic 10", "Topic 11", "Topic 12", "Topic 2", "Topic 3", "Topic 4", 
                                                                                                                       "Topic 5", "Topic 6", "Topic 7", "Topic 8", "Topic 9"), class = "factor"), 
                           Year = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 2L, 
                                              3L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 
                                              3L, 4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 
                                              9L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 
                                              8L, 9L, 1L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 6L, 7L, 8L, 
                                              9L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L, 4L, 5L, 
                                              6L, 7L, 8L, 9L, 2L, 3L, 4L, 5L, 6L, 7L, 8L), .Label = c("2011", 
                                                                                                      "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019"
                                              ), class = "factor"), Count = c(3L, 3L, 3L, 5L, 5L, 11L, 
                                                                              17L, 14L, 4L, 1L, 1L, 4L, 2L, 3L, 9L, 4L, 2L, 1L, 3L, 4L, 
                                                                              5L, 18L, 23L, 19L, 15L, 1L, 5L, 6L, 8L, 11L, 17L, 7L, 1L, 
                                                                              3L, 6L, 4L, 20L, 21L, 18L, 12L, 3L, 1L, 1L, 2L, 5L, 5L, 11L, 
                                                                              5L, 2L, 1L, 1L, 2L, 2L, 5L, 7L, 23L, 9L, 1L, 1L, 2L, 3L, 
                                                                              6L, 4L, 9L, 8L, 1L, 1L, 6L, 2L, 3L, 3L, 1L, 3L, 2L, 5L, 7L, 
                                                                              11L, 11L, 28L, 11L, 2L, 1L, 2L, 2L, 5L, 6L, 5L, 16L, 3L, 
                                                                              4L, 2L, 2L, 7L, 6L, 8L, 6L)), row.names = c(NA, -96L), class = "data.frame")

    dtd2 %>%
      complete(Topic, Year = unique(Year), fill = list(Count = 0)) %>% 
      filter(Topic %in% paste("Topic", input$select_topic_timeline)) %>% 
      ggplot(aes(x = Year, y = Count, colour = Topic, group = Topic)) + 
      geom_point() +
      geom_line() +
      labs(x = "Year", y = NULL, title = "Timeline")
  })
}

shinyApp(ui,server)

В качестве примечания, я бы также рекомендовал использовать пакет shinyWidgets для этого конкретного ввода, в частности shinyWidgets::pickerInput, а не ваниль shiny::selectInput. Я оставлю это решение на ваше усмотрение.

...