Я новичок в 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». У вас есть идеи, почему и как это решить?
У меня также есть два дополнительных вопроса, которые гораздо менее раздражают:
Большое вам спасибо за вашу помощь.
Он просто подсвечивает 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
Это как-то помогает или я неправильно понял, что вам нужно?
Хорошо, после бессонной ночи я действительно нашел решение, в основном благодаря удивительному руководству @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)
Поместите
browser()
непосредственно передmerged[...
и перезапустите приложение. Посмотрите, как выглядит результат.