In my app I want user to choose between two dataset (mtcars and iris), then to choose one variable from previously chosen dataset. The app will show the summary of that variable.
I can choose the dataset, however a problem arises when I'm trying to choose the variable - everytime I choose something, it returns to the first column available (eg. while choosing Iris as a db I can see only Sepal.Length). For a brief moment summary can be seen for that chosen variable
library(shiny)
library(dplyr)
db_cars <- mtcars
db_iris <- iris
# Define server logic required to summarize and view the selected dataset
server <- shinyServer(function(input, output, session) {
datasetInput <- reactive({
simple_name <- eval(as.symbol(paste(input$dataset)))
observe({
updateSelectInput(
session,
"variable",
choices = colnames(simple_name[1:ncol(simple_name)])
)
})
simple_name %>% pull (input$variable)
})
output$summary <- renderPrint({
dataset <- datasetInput()
summary(dataset)
})
})
# Define UI for dataset viewer application
ui <- shinyUI(pageWithSidebar(
headerPanel("Shiny Text"),
sidebarPanel(
selectInput("dataset", "Choose dataset",
choices = c("db_cars", "db_iris")),
selectInput("variable", "Choose variable",
choices = ""),
),
mainPanel(
verbatimTextOutput("summary"),
)
))
shinyApp(ui = ui, server = server)
You should separate the reactive element into two parts. One for the data selection, and one for variable selection.
server <- shinyServer(function(input, output, session) {
currentdata <- reactive({
simple_name <- eval(as.symbol(paste(input$dataset)))
updateSelectInput(
session,
"variable",
choices = colnames(simple_name[1:ncol(simple_name)])
)
simple_name
})
datasetInput <- reactive({
currentdata() %>% pull(input$variable)
})
output$summary <- renderPrint({
dataset <- datasetInput()
summary(dataset)
})
})
They way each is only dependent on one input value so you don't run into trouble trying to change the dataset when you are trying to change just the varible.
Related
so I want to make a data table in Shiny that displays only the number of rows that the user inputs. The only other input is which dataset the user wants to see (iris, diamond, or storms). But I can not figure out how to make the table so that it will let you switch between datasets and change the number of rows displayed, I can only do one or the other. I would really appreciate some help. I am really new to R so i'm sorry if this is a simple question. I've looked at similar questions and still can't figure it out. Thank you.(I also have a summary that is printed too but that works fine its just the table that is a problem).
ui <- fluidPage(
selectInput("dataset", "Choose Dataset", choices = c("iris", "storms", "diamonds")), # 3 dataset options for user to pick from
numericInput("num", "Row Number To Display", value = 0, min = 0, max = 100), # row number selection
verbatimTextOutput("summary"),
dataTableOutput("table")
)
server <- function(input, output, session) {
output$summary <- renderPrint({
dataset <- get(input$dataset)
summary(dataset)
})
output$table <- renderDataTable({
dataset <- get(input$dataset)
options = list(pageLength = input$num)
dataset
})
}
shinyApp(ui, server)
Subset the table to be displayed by input$num.
output$table <- renderDataTable({
dataset <- get(input$dataset)
dataset[seq_len(input$num), ]
})
Complete Code -
library(shiny)
ui <- fluidPage(
selectInput("dataset", "Choose Dataset", choices = c("iris", "storms", "diamonds")), # 3 dataset options for user to pick from
numericInput("num", "Row Number To Display", value = 0, min = 0, max = 100), # row number selection
verbatimTextOutput("summary"),
dataTableOutput("table")
)
server <- function(input, output, session) {
output$summary <- renderPrint({
dataset <- get(input$dataset)
summary(dataset)
})
output$table <- renderDataTable({
dataset <- get(input$dataset)
dataset[seq_len(input$num), ]
})
}
shinyApp(ui, server)
This is a sample application where in the table is displayed as per values selected from dropdown(more than 2 values).
Right now the user can select only from dropdown. But can we add additional feature where (say from excel there are values column wise
Now the user can copy this values and paste it on selectinput. Then these values should be taken in the selectinput.
Basically the user should be able to copy and paste values into selectinput widget
library(shiny)
library(DT)
dat <- mtcars
server <- function(input, output, session) {
output$ui_view_vars <- renderUI({
vars <- colnames(dat)
## using selectizeInput with drag_drop and DT
selectizeInput("view_vars", "Select variables to show:", choices = vars,
selected = "", multiple = TRUE,
options = list(plugins = list('drag_drop')))
})
output$dataviewer <- DT::renderDataTable({
if (is.null(input$view_vars)) return()
DT::datatable(dat[,input$view_vars])
})
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput("ui_view_vars")
),
mainPanel(
tabPanel("View", DT::dataTableOutput("dataviewer"))
)
)
)
shinyApp(ui = ui, server = server)
G'day awesome community
I am trying to make a dashboard of a dataframe that allows one to filter the dataframe by the levels within a column selected. This means a first pickerInput where the user selects the column, and then a second child pickerInput where the options are generated based on the column selected. I have figured out one way to make the pickerInputs dependent on each other, but for some reason when I try to apply the filtering, my dataframe has zero values and I cant see why?
Please see the reprex created with the mtcars dataset
library(shiny)
library(shinyWidgets)
library(dplyr)
library(DT)
data(mtcars)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(uiOutput('select_filter'),
uiOutput('filter')),
mainPanel(
dataTableOutput('table')
),
))
server <- function(input, output, session) {
data<-mtcars
categories<-c('cyl','vs','am','gear','carb')
output$select_filter <- renderUI({
pickerInput("select_filter", "Select flexi filter",
choices = levels(as.factor(categories))
)})
output$filter <- renderUI({
pickerInput("filter", "Flexi filter",
choices = unique(data[,input$select_filter]),
options = list('actions-box'=TRUE), multiple= TRUE,
selected = unique(data[,input$select_filter]))
})
filtered_data<-
#
reactive ({data %>% filter(input$select_filter %in% input$filter)
})
output$table<-renderDataTable(filtered_data())
}
shinyApp(ui, server)
Any help will be greatly appreciated! If any further information is required please let me know.
Cheers
In filter, use .data to get the column value using select_filter variable. Also included req so that it doesn't error out at the start when the input$select_filter is NULL.
filtered_data <-
reactive ({
req(input$select_filter)
data %>% filter(.data[[input$select_filter]] %in% input$filter)
})
Complete app code -
library(shiny)
library(shinyWidgets)
library(dplyr)
library(DT)
data(mtcars)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(uiOutput('select_filter'),
uiOutput('filter')),
mainPanel(
dataTableOutput('table')
),
))
server <- function(input, output, session) {
data<-mtcars
categories<-c('cyl','vs','am','gear','carb')
output$select_filter <- renderUI({
pickerInput("select_filter", "Select flexi filter",
choices = levels(as.factor(categories))
)})
output$filter <- renderUI({
pickerInput("filter", "Flexi filter",
choices = unique(data[,input$select_filter]),
options = list('actions-box'=TRUE), multiple= TRUE,
selected = unique(data[,input$select_filter]))
})
filtered_data<-
#
reactive ({
req(input$select_filter)
data %>% filter(.data[[input$select_filter]] %in% input$filter)
})
output$table<-renderDataTable(filtered_data())
}
shinyApp(ui, server)
First of all, I am so sorry if the main question (the title) of the post is not clearly enough. I didn't how to write a question with my problem.
Well, the thing is that I have two select inputs. The main one: Dataset, which have 2 options: 1) Cars and 2) Iris.
The other select input, it has information from the Cars' dataset and information from the Iris one.
I need to show the information from Cars if I select Cars and the information from Iris if I select Iris.
Now, my code is not able to do that. Simply it shows you the options to choose the datasets but in the second select input only shows the information from Cars.
I don't know how to do it, I have been a lot of posts but I couldn't get what I want.
For example this post Filter one selectInput based on selection from another selectInput? was very similar and I thought that I could do something similar, but he doesn't use a dataset from R...
My code:
library(shiny)
ui <- fluidPage(
titlePanel("Select a dataset"),
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Dataset",
choices = c("Cars" = "Cars", "Iris" = "Iris")),
uiOutput("select_cars"),
uiOutput("select_iris")
),
mainPanel(
verbatimTextOutput("text"),
verbatimTextOutput("text2")
)
)
)
server <- function(input, output) {
cars <- reactive({
data("mtcars")
cars <- rownames(mtcars)
return(cars)
})
iris <- reactive({
data("iris")
iris <- data.frame(unique(iris$Species))
colnames(iris) <- "iris"
return(iris)
})
output$select_cars <- renderUI({
selectInput(inputId = "options_cars", "Select one", choices = cars())
})
output$select_iris <- renderUI({
selectInput(inputId = "options_iris", "Select one iris", choices = iris())
})
output$text <- renderPrint(input$options_cars)
output$text2 <- renderPrint(input$options_iris)
}
#Run the app
shinyApp(ui = ui, server = server)
On the other hand I get an error: object of type ‘closure’ is not subsettable. But I don't know why.
Finally, I apologize if someone has already asked something similar before, I really have been looking all morning and I do not know how to solve it. (I am quite new at Shiny and I am trying to do my best).
Thanks very much in advance,
Regards
I have modified some of your code and added some JS functionality from shinyjs, which you may or may not find useful
You don't really need to create objects all the time if you only going to update the list, so we are going to use updateSelectInput to update the sliders
I used hidden functionality to hide the elements initially so they are invisible to begin with
I created dependency on input$dataset within observeEvent so we can update the sliders and hide and show both the sliders we dont want and the output we dont want
Also if your datasets are static, like mtcars and iris its best to take them outside the server.R so you dont do extra unnecessary work
Finally its always a good idea to add req so you're not creating any objects if they are NULL
Your original error was due to the fact that you were passing the dataframe and not the list or vector to the slider, try to print out the objects if you're unsure and see their types
library(shiny)
library(shinyjs)
ui <- fluidPage(
titlePanel("Select a dataset"),
useShinyjs(),
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Dataset",
choices = c("Cars" = "Cars", "Iris" = "Iris")),
hidden(selectInput(inputId = "options_cars", "Select one", choices = NULL)),
hidden(selectInput(inputId = "options_iris", "Select one iris", choices = NULL))
),
mainPanel(
verbatimTextOutput("text_cars"),
verbatimTextOutput("text_iris")
)
)
)
cars_data <- unique(rownames(mtcars))
iris_data <- as.character(unique(iris$Species))
server <- function(input, output, session) {
observeEvent(input$dataset,{
if(input$dataset == "Cars"){
show('options_cars')
hide('options_iris')
show('text_cars')
hide('text_iris')
updateSelectInput(session,"options_cars", "Select one", choices = cars_data)
}else{
show('options_iris')
hide('options_cars')
show('text_iris')
hide('text_cars')
updateSelectInput(session,"options_iris", "Select one iris", choices = iris_data)
}
})
output$text_cars <- renderPrint({
req(input$options_cars)
input$options_cars
})
output$text_iris <- renderPrint({
req(input$options_iris)
input$options_iris
})
}
#Run the app
shinyApp(ui = ui, server = server)
Here is a code that allows the switch by selectInput
library(shiny)
library(datasets)
ui <- fluidPage(
titlePanel("Select a dataset"),
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Dataset",
choices = c("Cars" = "Cars", "Iris" = "Iris")),
##------removed this---------------
# uiOutput("select_cars"),
#uiOutput("select_iris")
##------------------------------
uiOutput("select_by_input")
),
mainPanel(
verbatimTextOutput("text")
# verbatimTextOutput("text2")
)
)
)
server <- function(input, output) {
cars <- reactive({
data("mtcars")
cars <- rownames(mtcars)
return(cars)
})
iris <- reactive({
# data("iris")
# iris <- data.frame(unique(iris$Species))
data('iris')
#colnames(iris) <- "iris"
# iris_names <- as.character(unique(iris$Species) )
iris_names <- c('a','b','c')
return(iris_names)
})
##------removed this---------------
# output$select_cars <- renderUI({
# selectInput(inputId = "options_cars", "Select one", choices = cars())
# })
#
# output$select_iris <- renderUI({
# selectInput(inputId = "options_iris", "Select one iris", choices = iris())
# })
#-----------------------------
output$select_by_input <- renderUI({
if (input$dataset=='Cars'){
selectInput(inputId = "options_x", "Select one", choices = cars())
}else if (input$dataset=='Iris'){
selectInput(inputId = "options_x", "Select one iris", choices = iris())
}
})
output$text <- renderPrint(input$options_x)
}
#Run the app
shinyApp(ui = ui, server = server)
the object of type ‘closure’ is not subsettable. error is caused by the iris data not being loaded after running the app. I used iris_names <- c('a','b','c') to demonstrate the dynamic change by selectInput
I want to create a shiny app where the user can view data from two different datasets: 'new' and 'central'.
I use the below code:
# Define UI for application
fluidPage(
titlePanel("Public services"),
#tell shiny where to display the objects
#let the user choose the dataset they want to interact with
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose dataset:",
choices = c("Local government", "Central Government")),
uiOutput('name'),
uiOutput('type'),
uiOutput('service')),
#display an output object on the main manel
mainPanel(
# Output: Verbatim text for data summary ----
h4("Summary"),
verbatimTextOutput("summary"),
h4("Observations"),
DT::dataTableOutput("table")
))
)
# Define UI for application that
function(input, output) {
# A reactive expression to return the dataset corresponding to the
user choice
datasetInput <- reactive({
switch(input$dataset,
"Central Government" = central,
"Local Government" = local)
})
#Filter data based on selections
#name
output$name = renderUI({
selectInput('name', h5('Department or Local authority name'),
choices = names(datasetInput()))
})
output$type = renderUI({
selectInput('type', h5('Service type'), choices =
names(datasetInput()))
})
output$service = renderUI({
selectInput('service', h5('Service'), choices =
names(datasetInput()))
})
output$table <- DT::renderDataTable({
datasetInput()
})
}
Only the 'central' dataset is viewed in the dataframe, and the input options are only visible from the 'central' dataset.
The following code, which is just your code with some pieces left out and a different dataset, runs fine for me. Without a reproducible example it is
a bit difficult to help you, since I am unable to reproduce the erroneous behavior. It would be great if you could add a reproducible example, for tips on that see for example here or here.
# Define UI for application
ui<- fluidPage(
titlePanel("Public services"),
#tell shiny where to display the objects
#let the user choose the dataset they want to interact with
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose dataset:",
choices = c("mtcars2", "mtcars10"))),
mainPanel(
DT::dataTableOutput("table")
))
)
# Define UI for application that
server<-function(input, output) {
# A reactive expression to return the dataset corresponding to the
datasetInput <- reactive({
switch(input$dataset,
"mtcars2" = head(mtcars,2),
"mtcars10" = head(mtcars,10))
})
output$table <- DT::renderDataTable({
datasetInput()
})
}
shinyApp(ui,server)