Reputation:
I am attempting to filter rows from a data frame, such as "mtcars", using the selectInput function in shiny. So a user will select which car he wants to view and the outputTable will show only stats from the selected car. In the selectInput example, the selection works on columns:
## Only run examples in interactive R sessions
if (interactive()) {
# basic example
shinyApp(
ui = fluidPage(
selectInput("variable", "Variable:",
c("Cylinders" = "cyl",
"Transmission" = "am",
"Gears" = "gear")),
tableOutput("data")
),
server = function(input, output) {
output$data <- renderTable({
mtcars[, c("mpg", input$variable), drop = FALSE]
}, rownames = TRUE)
}
)
}
However, I am trying to use dplyr to filter out the cars based on the user input selected car:
library(shiny)
library(dplyr)
#####Just adding a column name to mtcars for the cars column####
#cars <- mtcars
#mtcars <-setNames(cbind(rownames(cars), cars, row.names = NULL),
# c("cars", "mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb"))
if (interactive()) {
shinyApp(
ui = fluidPage(
selectInput("variable", "Pick a Car: ",
c("All" = "All Cars",
"Ford" = "Ford",
"Volvo" = "Volvo",
"Ferrari" = "Ferrari",
"Fiat" = "Fiat",
"Merc" = "Merc")),
tableOutput("data")
),
server = function(input, output) {
output$cars <- renderText({
mtcars %>%
filter(mtcars$cars %in% as.character(input$variable))
})
output$data <- renderTable({
output$cars
})
}
)
}
Any suggestions will be much appreciated!
Upvotes: 1
Views: 2850
Reputation: 9809
First, the input$variable in your 2nd example is not known as your selectInput-ID is "cars". Then you dont use the renderedText output and so the filtering never happens. And last, the possible choices are not at hand in the mtcars data. So no matter what, it will never find any data for the table.
I wrote a reproducible example, changing the selectable choices to actual names of the mtcars data.
rm(list=ls())
cars <- mtcars
mtcars <-setNames(cbind(rownames(cars), cars, row.names = NULL),
c("cars", "mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb"))
library(shiny)
library(DT)
if (interactive()) {
shinyApp(
ui = fluidPage(
selectInput(inputId = "variable", label = "Pick a Car: ",choices =
c("Mazda RX4 Wag" = "Mazda RX4 Wag",
"Merc 280" = "Merc 280",
"Volvo 142E" = "Volvo 142E",
"Duster 360" = "Duster 360",
"Lotus Europa" = "Lotus Europa"), selected = "Mazda RX4 Wag"),
verbatimTextOutput("cars"),
tableOutput("data")
),
server = function(input, output) {
carReact <- reactiveValues(car=NULL)
output$cars <- renderText({
txt <- mtcars[mtcars$cars %in% as.character(input$variable),]
## Use regex() or match() for example, if you only want partial matching of the car names.
carReact$car <- txt
paste(txt, collapse = ";")
})
output$data <- renderTable({
req(carReact$car)
datatbl <- carReact$car
as.data.frame(datatbl)
})
}
)
}
The selected Car name is saved in a reactiveValue (carReact) and it is assigned in the renderText function. And renderText is not able to print out lists, so you have to mere it to 1 variable or use the paste() function.
Upvotes: 1
Reputation: 13680
You only need renderTable()
and pass it the filtered dataframe.
To filter the dataframe we need to find those rows where input$cars
is present in the rowname (or the added column car
).
But this won't work when selecting All
, that's why we use the condition input$cars == 'All Cars'
.
This should work:
shinyApp(
ui = fluidPage(
selectInput("cars", "Pick a Car: ",
c("All" = "All Cars",
"Ford" = "Ford",
"Volvo" = "Volvo",
"Ferrari" = "Ferrari",
"Fiat" = "Fiat",
"Merc" = "Merc")),
tableOutput("data")
),
server = function(input, output) {
mtcars$car <- rownames(mtcars)
output$data <- renderTable({
mtcars %>%
filter(stringr::str_detect(car, as.character(input$cars)) | input$cars == 'All Cars')
})
}
)
Upvotes: 2