Проблема с привязкой графика и таблицы к нескольким входам

Я новичок в Shiny, и у меня проблема с отзывчивостью моего графика и таблицы.

Мой набор данных merged состоит из двух переменных (длины и размера), каждая из которых имеет две отдельные категории: Length может быть либо Large, либо Small, либо Size может быть либо Long, либо short. Также есть две разные единицы: в Volume и в Count. Я хотел бы создать приложение с одним графиком, где либо Length, либо Size будут отображаться либо в Volume, либо в Count.

Когда я упрощаю эту задачу, используя только часть набора данных merged, то есть набор данных data1 или data2 ниже, все работает хорошо, поскольку у меня есть только один selectInput() (чтобы выбрать Category).

Вот рабочий фиктивный код, в котором используется только data1:

data1 <- data.frame(variable = rep("Size", 24), category = rep(c("Large","Small"), each = 12), unit = rep(c("Volume", "Count"), each = 6), date = rep(c("Jan 2000", "Feb 2000", "Mar 2000", "Apr 2000", "May 2000", "Jun 2000"), times = 2), quantity = c(0.9,2,3.1,3.7,4.7,5.9,106.6,207.3,329,450.6,513.3,610,6.5,9.2,10,10.8,10.7,13.6,802.6,765.3,996,1076.6,1151.3,1196))
data1$date <- as.yearmon(paste(data1$date),"%b %Y")
data2 <- data.frame(variable = rep("Length", 24), category = rep(c("Long","Short"), each = 12), unit = rep(c("Volume", "Count"), each = 6), date = rep(c("Jan 2000", "Feb 2000", "Mar 2000", "Apr 2000", "May 2000", "Jun 2000"), times = 2), quantity = c(1.8,6.8,4.3,1.6,8.4,11.8,362.4,290.2,148,811,1026.6,2074,9.1,4.1,18,21.6,36.3,19,361.1,1377.5,1992,3660.4,1611.8,538.2))
data1$date <- as.yearmon(paste(data1$date),"%b %Y")
merged <- rbind(data1, data2)

# Define UI for application that draws time-series
ui <- fluidPage(

  # Application title
  titlePanel("Dummy shiny"),

  # Create filters 
  fluidRow(
    column(4,
           selectInput("unit", label = h4("Display the dummy data in:"), 
                       unique(as.character(data1$unit)))
    ),
    column(4,
           sliderInput("date", label = h4("Select time range:"),
                       2000, 2000.5, value = c(2000, 2000.5), step = 0.1)
    )
  ),
  # Create a new row for the graph or the table (one in each tab)
  tabsetPanel(
    tabPanel("Graphical view", plotOutput("distPlot")),
    tabPanel("Data", dataTableOutput("distTable")))
)

# Define server logic required to draw the wanted time-series
server <- function(input, output) {
  dataInput <- reactive({
    data1[data1$unit==input$unit,]
  })
  output$distPlot <- renderPlot({
    ggplot(dataInput(), aes(x = date, y = quantity, fill = category)) +
      geom_area(position = "stack") +
      xlab("") + ylab("") +
      scale_x_continuous(limits = input$date, expand = c(0, 0)) +
      scale_y_continuous(expand = c(0, 0))
  })
  output$distTable <- renderDataTable({
    dataInput()
  },
  extensions = "Buttons",
  options = list(
    scrollY = "300px", pageLength = 10, scrollX = TRUE, dom = "Bftsp",
    buttons = c("copy", "csv", "excel"))
  )
}

# Run the application 
shinyApp(ui = ui, server = server)

При попытке использовать набор данных merged вместо набора данных data1 мне нужно добавить еще один selectInput() (чтобы выбрать Variable), но при запуске кода я получаю сообщение об ошибке.

В приведенном выше коде я просто добавил этот бит в fluidRow() :

column(4,
           selectInput("var", label = h4("Choose variable to display:"), 
                       unique(as.character(merged$variable)))
    )

и заменил бит dataInput на:

reactive({
    merged[merged$unit==input$unit | merged$variable==input$var,]
  })

Он говорит: «отсутствует значение там, где нужно TRUE/FALSE». У вас есть идеи, почему и как это решить?

У меня также есть два дополнительных вопроса, которые гораздо менее раздражают:

  1. Есть ли способ убедиться, что таблица также реагирует на временной диапазон?
  2. Есть ли способ сохранить даты как «%b %Y» вместо дробей в таблице?

Большое вам спасибо за вашу помощь.

Поместите browser() непосредственно перед merged[... и перезапустите приложение. Посмотрите, как выглядит результат.

Roman Luštrik 30.05.2019 19:44

Он просто подсвечивает browser() желтым цветом, и появляются кнопки продолжения и остановки... В консоли написано: Warning: Error in if: missing value where TRUE/FALSE needed 178: plyr::id 177: add_group 176: f 175: l$compute_aesthetics 174: f 173: by_layer 172: ggplot_build.ggplot 170: print.ggplot 162: func 160: f 159: Reduce 150: do 149: hybrid_chain 121: drawPlot 107: <reactive:plotObj> 91: drawReactive 78: origRenderFunc 77: output$distPlot 1: runApp Это как-то помогает или я неправильно понял, что вам нужно?

Fred-LM 31.05.2019 12:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
42
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хорошо, после бессонной ночи я действительно нашел решение, в основном благодаря удивительному руководству @deanattali, доступному по адресу: https://deanattali.com/blog/building-shiny-apps-tutorial/.

Проблема была связана с тем, как я ранее подустанавливал свои данные. Вот полный рабочий код:

library(shiny)
library(DT)
library(zoo)
library(ggplot2)
library(dplyr)
data1 <- data.frame(variable = rep("Size", 24), category = rep(c("Large","Small"), each = 12), unit = rep(c("Volume", "Count"), each = 6), date = rep(c("Jan 2000", "Feb 2000", "Mar 2000", "Apr 2000", "May 2000", "Jun 2000"), times = 2), quantity = c(0.9,2,3.1,3.7,4.7,5.9,106.6,207.3,329,450.6,513.3,610,6.5,9.2,10,10.8,10.7,13.6,802.6,765.3,996,1076.6,1151.3,1196))
data2 <- data.frame(variable = rep("Length", 24), category = rep(c("Long","Short"), each = 12), unit = rep(c("Volume", "Count"), each = 6), date = rep(c("Jan 2000", "Feb 2000", "Mar 2000", "Apr 2000", "May 2000", "Jun 2000"), times = 2), quantity = c(1.8,6.8,4.3,1.6,8.4,11.8,362.4,290.2,148,811,1026.6,2074,9.1,4.1,18,21.6,36.3,19,361.1,1377.5,1992,3660.4,1611.8,538.2))
merged <- rbind(data1, data2)
merged$date <- as.yearmon(paste(merged$date),"%b %Y")

# Define UI for application that draws time-series
ui <- fluidPage(

  # Application title
  titlePanel("Dummy shiny"),

  # Create filters 
  fluidRow(
    column(4,
           selectInput("variableInput", label = h4("Display the dummy data in:"), 
                       unique(merged$variable))),
    column(4,
           selectInput("unitInput", label = h4("Display the dummy data in:"), 
                       unique(merged$unit))),
    column(4,
           sliderInput("dateInput", label = h4("Select time range:"),
                       2000, 2000.5, value = c(2000, 2000.5), step = 0.1)
    )
  ),
  # Create a new row for the graph or the table (one in each tab)
  tabsetPanel(
    tabPanel("Graphical view", plotOutput("distPlot")),
    tabPanel("Data", dataTableOutput("distTable")))
)

# Define server logic required to draw the wanted time-series
server <- function(input, output) {
  filtered <- reactive({
    merged %>%
      filter(variable == input$variableInput,
             unit == input$unitInput,
             date >= input$dateInput[1],
             date <= input$dateInput[2]
    )%>%
    select(-c(1,3))
})
  })
  output$distPlot <- renderPlot({
    ggplot(filtered(), aes(x = date, y = quantity, fill = category)) +
      geom_area(position = "stack") +
      xlab("") + ylab("") +
      scale_x_continuous(limits = input$date, expand = c(0, 0)) +
      scale_y_continuous(expand = c(0, 0))
  })
  output$distTable <- renderDataTable({
    filtered()
  },
  extensions = "Buttons",
  options = list(
    scrollY = "300px", pageLength = 10, scrollX = TRUE, dom = "Bftsp",
    buttons = c("copy", "csv", "excel"))
  )
}

# Run the application 
shinyApp(ui = ui, server = server)

Другие вопросы по теме