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)
Related
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)
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
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.
I am making a shiny where I can read a CSV file, and then be able to replace a selected column with a new value (which in this case replaced by 0).
I usually use a mutate function to do this.
How to use mutate function properly in shiny, when the selected column is also an input?
ui <- fluidPage(fileInput('file1', h2('Dataset Settings'),
accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv')),
tags$hr(),
selectInput(inputId = "replaceCol",
label = "Select numeric with missing value",
choices = c()),
actionButton(inputId = "confirm",
label = "Replace with 0"),
tags$hr(),
dataTableOutput("Original")
)
server <- function(input, output, session){
data_set <- reactive({
inFile <- input$file1
read.csv(inFile$datapath)
})
observe({
req(input$file1)
temp <- colnames(data_set())
col <- list()
col[temp] <- temp
updateSelectInput(session,
inputId = "replaceCol",
choices = col,
selected = "")
})
output$Original <- renderDataTable({
data_set()
})
observeEvent(input$confirm,{
data_set() <- mutate(data_set(), replace(input$replaceCol, TRUE, 0))
})
}
shinyApp(ui = ui, server = server)
Your code has several issues:
if a UI element depends on some calculation from the server, it is best to use renderUI
you can't directly assign something to the output of a reactive function
if you want to dynamically generate variable names in dplyr, it's a bit more complicated
Therefore, I use a reactiveVal to store your dataset and update it, if a column is changed. I'm not completely satisfied with the use of an observer to update the data_set() when a new file is chosen, I'm happy to hear if someone has a better solution.
library(shiny)
library(dplyr)
ui <- fluidPage(fileInput('file1', h2('Dataset Settings'),
accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv')),
tags$hr(),
uiOutput(outputId = "UI_replaceCol"),
actionButton(inputId = "confirm",
label = "Replace with 0"),
tags$hr(),
dataTableOutput("Original")
)
server <- function(input, output, session){
# reactive variable to store the data
data_set <- reactiveVal()
observeEvent(input$file1, {
inFile <- input$file1
data <- read.csv(inFile$datapath)
data_set(data)
})
output$UI_replaceCol <- renderUI({
req(data_set())
col <- colnames(data_set())
selectInput(inputId = "replaceCol",
label = "Select numeric with missing value",
choices = col)
})
output$Original <- renderDataTable({
data_set()
})
observeEvent(input$confirm,{
data <- data_set() %>%
mutate(!!as.symbol(input$replaceCol) :=
replace(!!as.symbol(input$replaceCol), TRUE, 0))
data_set(data)
})
}
shinyApp(ui = ui, server = server)
I am having difficulty implementing this code on a more complicated setup that I have. My goal is to let the user change column values with the projected values rendered from numericInput button. Global.R is not an option as there are many operations placed on the dataset before the final version is reached. I have everything setup other than being able to observe the input$action and change the dataframe when an action occurs.
ui.R
shinyUI(
fluidPage(
titlePanel("Basic DataTable"),
# Create a new row for the table.
fluidRow(
selectInput("select", label = h3("Select box"),
choices = unique(data$Projection),
selected = unique(data$Projection)[1]),
numericInput("num", label = h3("Numeric input"), value = unique(data$Projection)[1]),
submitButton(text = "Apply Changes", icon = NULL),
dataTableOutput(outputId="table")
)
)
)
server.R
library(shiny)
# Load the ggplot2 package which provides
# the 'mpg' dataset.
# Given that you are not plotting this line is
### useless library(ggplot2)
# Define a server for the Shiny app
shinyServer(function(input, output) {
# Filter data based on selections
output$table <- renderDataTable({
data$User_Prediction[data$Projection==input$select] <<- input$num
data
})
})
global.r
data <- as.data.frame(c(98,99,34))
names(data) <- "Projection"
data$User_Prediction <- 0
Data is stored in server.R as such
data <-reactive({
...
...
...
data
})
I am trying to bring in data which is stored in the reactive function into
d <- reactiveValues(dat=data)
I have tried
d <- data()
d <- data
d <- reactiveValues(dat=data)
Is there any way I could access the data, because otherwise your code works.
If you want to do this without observeEvent you could do this:
data <- as.data.frame(c(98,99,34))
names(data) <- "Projection"
data$User_Prediction <- 0
ui <- shinyUI(
fluidPage(
titlePanel("Basic DataTable"),
# Create a new row for the table.
fluidRow(
column(12,
selectInput("select", label = h3("Select box"),
choices = unique(data$Projection),
selected = unique(data$Projection)[1]),
numericInput("num", label = h3("Numeric input"), value = unique(data$Projection)[1]),
actionButton('btn',"Apply Changes"),
dataTableOutput(outputId="table")
)
)
)
)
server <- shinyServer(function(input, output) {
d <- reactive({
data
})
dat <- reactiveValues(dat=NULL)
observe({
dat$dat <- d()
})
observe({
input$btn
isolate({
num <- input$num
sel <- input$select
})
dat$dat$User_Prediction[dat$dat$Projection==sel] <- num
#d2 <- dat
})
# Better way
# observeEvent(input$btn,{
# dat$dat$User_Prediction[dat$dat$Projection==sel] <- num
# })
# Filter data based on selections
output$table <- renderDataTable({
dat$dat
})
})
shinyApp(ui=ui,server=server)