Related
I want to update one of my selectInputs, "variable" with a reactive list of countries that will change depending on the dataset that is selected in another selectInput, "Databases". I want the default list of choices to be the "Home File" dataset that is loaded when the app runs but I want to have the option of switching to an uploaded file. The files I plan to upload will all have the list of countries under the "Countries" column to match the home_df column. Ideally the list will refresh anytime the dataset is switched.
So far I have tried this but cant seem to return the values I want:
Values <- c(145540,145560, 157247, 145566)
Countries <- c(US, Canada, Ireland, Spain)
Zipcodes <- c(145592, 145560, 145566, NA)
home_df <- data.frame(Values , Countries , Zipcodes )
ui <- fluidPage(
tabPanel(
"first_plot",
tabsetPanel(
id = "firstPanel",
type = "tabs",
tabPanel("File Upload",
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput(
"file1",
"Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
# Horizontal line ----
tags$hr(),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons(
"sep",
"Separator",
choices = c(
Comma = ",",
Semicolon = ";",
Tab = "\t"
),
selected = ","
),
# Input: Select quotes ----
radioButtons(
"quote",
"Quote",
choices = c(
None = "",
"Double Quote" = '"',
"Single Quote" = "'"
),
selected = '"'
),
# Horizontal line ----
tags$hr(),
# Input: Select number of rows to display ----
radioButtons(
"disp",
"Display",
choices = c(Head = "head",
All = "all"),
selected = "head"
)
),
mainPanel(# Output: Data file ----
tableOutput("contents"))
)),
tabPanel("first_plot",
uiOutput("box"))
server <- function(input, output, session) {
my_data <- reactive({
inFile <- input$file1
req(inFile)
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch({
df_x <<- read.csv(
inFile$datapath,
header = input$header,
sep = input$sep,
quote = input$quote
)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
})
if (input$disp == "head") {
return(head(df_x))
}
else {
return(df_x)
}
})
}
datasetInput <- reactiveValues(
if (input$exp_pr_box == "Home File"){
dataset <- home_df
}
else if (input$exp_pr_box == "Uploaded DB"){
dataset <- my_data()
}
return(dataset)
)
md <- reactiveValues(
list = datasetInput$Countries
)
observeEvent(datasetInput(),
updateSelectInput(session, "variable", choices=md()))
output$box <- renderUI({
tabPanel(
"first_plot",
sidebarPanel(
selectInput(
"exp_pr_box",
"Database",
choices = c("Home File", "Uploaded DB")
), ----
selectInput("variable", "Selection:", choices=NULL, selected = NULL
)
)
),
mainPanel(
h3("plot title", align = "center"),
plotlyOutput("plot", height = '1000px', width = "100%")
)
)
})
output$contents <- renderTable({
my_data()
})
output$plot <- renderPlotly(
ggplot(dx) +
geom_boxplot(col = c("#69b3a2", "red")) +
geom_line(data = dx, aes(group = paired), color =
"grey"))
shinyApp(ui, server)
I was able to solve the issue with the help of this post (R Shiny - How to update a dependent reactive selectInput before updating dependent reactive plot)
And by storing the list in the reactive. For some reason using the names function as was done in the example did not output the list for me but worked after removing it
md <- reactive({
my_list = input_dataset()
})
observeEvent(input$exp_pr_box, {
freezeReactiveValue(input, "variable")
updateSelectInput(session = session, inputId = "variable", choices = unique(str_to_title(md())))
})
As stated in the title, I'm trying to use Shiny in R to create a program that reads a csv file uploaded by the user, after which the user can select a variable from that file to view a plot that is plotted by ggplot. I'm trying to achieve this over two tabs, the first tab will read the file and the second tab will get the user to select the variable to view the plot.
My codes are as below. Currently, I am able to successfully read the user's file but I am not able to plot based on the variable selected (I currently only have 1 variable "Location" for demo). (HomeWTaxAmt is the y variable to plot against).
library(shiny)
library(ggplot2)
library(data.table)
library(RColorBrewer)
options(scipen=1000)
ui <- fluidPage(
navbarPage("User Interface:",tabPanel("Upload",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE),
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
tags$hr(),
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head"),
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"')),
mainPanel(
verbatimTextOutput("summary"),
tableOutput("contents")
))),
tabPanel("Graphing",
titlePanel("Plotting Graphs"),
sidebarLayout(
sidebarPanel(
selectInput("variable", "Variable:",
list("Location"))),
mainPanel(
h3(textOutput("caption")),
plotOutput("ggplot")
)
))
))
server <- function(input, output) {
output$contents <- renderTable({
req(input$file1)
library(data.table)
data <- fread(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
if(input$disp == "head") {
return(head(data))
}
else {
return(data)
}
})
output$summary <- renderPrint({
summary(data)
})
formulaText <- reactive(function() {
paste("HomeWTaxAmt ~", input$variable)
})
output$caption <- renderText(function() {
formulaText()
})
output$ggplot <- renderPlot(function() {
data <- fread(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
if(is.null(data)) return(NULL)
# check for the input variable
ggplot(data, aes(x=reorder(factor(data[input$variable]), -abs(HomeWTaxAmt), function(x){sum(x)}),
weight = abs(HomeWTaxAmt), fill = factor(data[input$variable]))) + geom_bar(show.legend=FALSE) + xlab(input$variable) +
scale_fill_manual(values=brewer.pal(n = 12, name = "Paired"))
})
}
shinyApp(ui, server)
As I did not have access to your exact .csv files I had to make some adjustments to the plotting command, but I'm pretty sure you can go from there and get it to work with your data. Please note that not loading a .csv file now gives you errors on the first tab, which dissapear as soon as data is loaded. You might want to use some ifelse switches here to ensure the end-user doesn't have to see these R-errors.
Here's the code that plots a plot as intended based on some sample data I had:
library(shiny)
library(ggplot2)
library(data.table)
library(RColorBrewer)
options(scipen=1000)
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# I didn't change anything in this section
ui <- fluidPage(
navbarPage("User Interface:",tabPanel("Upload",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE),
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
tags$hr(),
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head"),
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"')),
mainPanel(
verbatimTextOutput("summary"),
tableOutput("contents")
))),
tabPanel("Graphing",
titlePanel("Plotting Graphs"),
sidebarLayout(
sidebarPanel(
selectInput("variable", "Variable:",
list("Location"))),
mainPanel(
h3(textOutput("caption")),
plotOutput("ggplot")
)
))
))
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
server <- function(input, output, session) { # make sure to include "session" here, in order to update your inputs later
# create an reactive upload to access your data more quickly and easily
reactive_data <- reactive({
print(input$file1$datapath)
data <- fread(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
return(data)
})
# preview
# no library(data.table) required here, as its already loaded at the beginning of the script)
output$contents <- renderTable({
# load your data
data <- reactive_data()
if(input$disp == "head") {
return(head(data))
}
else {
return(data)
}
})
output$summary <- renderPrint({
summary(reactive_data())
})
formulaText <- reactive({ # no need for function() here
paste("HomeWTaxAmt ~", input$variable)
})
output$caption <- renderText({
formulaText()
})
output$ggplot <- renderPlot({
# load your data
data <- reactive_data()
# to only plot when data is not NULL, make sure to include the plotting command in the if-else statement
# no data
if(is.null(data)){
return(NULL)
}else{
# data
# update your selectInput first, so that all the variables match your .csv headers
updateSelectInput(session, "variable",
choices = colnames(data),
selected = input$variable) # this keeps the input on the last thing selected on tab-change
# check for the input variable
# I used aes_string here so that indexing the colnames works
# you'll have to adjust the plotting command to your needs as my .csv files aren't the same as yours
plot <- ggplot(data, aes_string(x=colnames(data)[colnames(data) == input$variable], colnames(data)[length(colnames(data))]))+
geom_bar(stat="identity")
# Display your plot
print(plot)
}
})
}
shinyApp(ui, server)
Modified your code a bit and i hope it helps you.
library(shiny)
library(ggplot2)
ui <- fluidPage(
navbarPage("User Interface:",tabPanel("Upload",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE),
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
tags$hr(),
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head"),
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"')),
mainPanel(
verbatimTextOutput("summary"),
tableOutput("contents")
))),
tabPanel("Graphing",
titlePanel("Plotting Graphs"),
sidebarLayout(
sidebarPanel( uiOutput("variable_x"),
uiOutput("variable_y")),
mainPanel(
h3(textOutput("caption")),
plotOutput("plot")
)
))
))
server <- function(input, output, session) {
onSessionEnded(stopApp)
data <- reactive({
req(input$file1)
df <- read.csv(input$file1$datapath, header = input$header, sep = input$sep, quote = input$quote)
return(df)
})
output$contents <- renderTable({
if (input$disp == "head") {
return(head(data()))
}
else {
return(data())
}
})
output$summary <- renderPrint({
summary(data())
})
output$variable_x <- renderUI({
selectInput("variableNames_x", label = "Variable_X", choices = names(data()))
})
output$variable_y <- renderUI({
selectInput("variableNames_y", label = "Variable_Y", choices = names(data()) )
})
dat <- reactive({
test <- data.frame(data()[[input$variableNames_x]], data()[[input$variableNames_y]])
colnames(test) <- c("X", "Y")
return(test)
})
output$plot <- renderPlot({
if (is.null(data)) { return(NULL)
} else {
ggplot(dat(),aes(x = X,y = Y)) + geom_point(colour = 'red',height = 400,width = 600) +
labs(y = input$variableNames_y,
x = input$variableNames_x,
title = "ggplot")
}
})
}
shinyApp(ui, server)
Note : I have changed your ggplot function but you can change as per your requirement.
I am trying to make a simple shiny app that takes information from a csv file and produces a table and two graphs. The content appears to be loading correctly but I can not seem to get the output to go within the specified tab, making the output appear cluttered and difficult to read. Any help is appreciated. Thank you in advance
library(ggplot2)
library(plater)
server <- function(input, output) {
output$table1 <- renderTable({
req(input$file1)
df <- read_plate(input$file1$datapath)
if(input$disp == "head") {
return(head(df))
}
else {
return(df)
}
data <- reactive({
read_plate(input$file1$datapath)
})
})
{output$Plot1 <- renderPlot({
req(input$file1)
df <- read_plate(input$file1$datapath)
ggplot(df, aes(x=Column, y=Row, size = 20, color = "variabley")) + geom_point()
})
}
output$vx <- renderUI({
req(input$file1)
df <- read_plate(input$file1$datapath)
selectInput("variablex", "Select the (X) Variable", choices = names(df))
})
output$vy <- renderUI({
req(input$file1)
df <- read_plate(input$file1$datapath)
selectInput("variabley", "Select the (y) Variable", choices = names(df))
})
output$p <- renderPlot({
req(input$file1)
df <- read_plate(input$file1$datapath)
ggplot(df, aes(input$variablex, input$variabley, size = 20)) + geom_point()
})
}
ui <- fluidPage(
titlePanel("Enrichment Analysis"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
# Input: Select quotes ----
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"'),
#Checkbox
# Horizontal line ----
tags$hr(),
# Input: Select number of rows to display ----
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head")
),
mainPanel(
tabsetPanel(type = "tab",
tabPanel("Plot", fluid = TRUE,
sidebarLayout(
sidebarPanel(selectInput("colm", "Variable", choices = names(df), selected = "")),
mainPanel(
plotOutput("Plot1")
)
)
),
tabPanel("Plate"),
sidebarPanel(
uiOutput("vx"),
uiOutput("vy"),
mainPanel(plotOutput("p", width = "70%"))
),
tabPanel("Comparison"),
tabPanel("Table")),
tableOutput("table1")
)
)
)
shinyApp(ui, server )
below is a shiny app to upload a rda or csv file. What I need is only show the checkboxinput and radiobutton widgets only when csv is selected as the file type in the selectinput. When rda is selected, do not show those widgets.
library(shiny)
library(DT)
##---------------------------------------------------------------
## ui
##---------------------------------------------------------------
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# select a file type
selectInput('filetype', label = h5(strong('Please select a file type')),
choices = c('rda', 'csv'),
selected = 'rda'),
# Input: Select a file ----
fileInput("file1", "Choose a file",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
# Input: Select quotes ----
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"')
),
#------------------------------Main Panel--------------------
mainPanel(
DT::dataTableOutput("data.table")
)
)
)
##---------------------------------------------------------------------
# server
##---------------------------------------------------------------------
options(shiny.maxRequestSize=30*1024^2)
server <- function(input, output, session) {
dt <- reactive ({
if (input$filetype %in% 'rda') {
load (input$file1$datapath)
df
} else {
read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
}
})
output$data.table <- DT::renderDataTable({
req(input$file1)
DT::datatable(dt(),
options = list(orderClasses = TRUE,
lengthMenu = c(5, 10, 20), pageLength = 5))
})
}
runApp(shinyApp(ui=ui, server=server))
Really appreciate it if anyone can help me with that. I have no clue how to achieve that.
Here's a sample of how to do build a dynamic UI that will only show the radio buttons if the file type selected is 'csv'. Refer to https://shiny.rstudio.com/articles/dynamic-ui.html for more.
library(shiny)
ui <- fluidPage(
selectInput(
"select",
label = "File Type",
choices = list("csv", "rda"),
selected = c("csv")
),
conditionalPanel(
condition = "input.select == 'csv'",
radioButtons(
"radio",
label = "Separator",
choices = list("commas", "tabs", "spaces")
)
)
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
I am trying a small shiny app wherein I load a CSV file from the local directory and then select specific columns from the dataframe and use this subsetted dataframe for further data analysis.
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
fileInput("dataset", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
# Include clarifying text ----
#helpText(em("Note: This app requires file in csv format only!!")),
helpText(em("Note:Select all the inputs and click on button as given below to exectute the app")),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
selectInput("select", "Select columns to display", names(datasetInput), multiple = TRUE),
actionButton("update", "Update Data set", class = "btn-primary",style='padding:4px; font-size:120%')
),
# Show a plot of the generated distribution
mainPanel(
h2('The Mydata'),
dataTableOutput('mytable')
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
datasetInput <- eventReactive(input$update, {
validate(need(input$dataset != "", "Please select a data set in csv format only!!!"))# custom error message on opening the app
read.csv(input$dataset$datapath,
header = input$header,
sep = input$sep)
}, ignoreNULL = FALSE)
dataset <- reactive({
df_input<-datasetInput()
df_input$x<-NULL
df_input
})
output$mytable = renderDataTable({
columns = names(dataset)
if (!is.null(input$select)) {
columns = input$select
}
dataset[,columns,drop=FALSE]
})
}
# Run the application
shinyApp(ui = ui, server = server)
Looking in some SO answers;got a few; one as given below:
shiny allowling users to choose which columns to display
But this answer, the dataset is predefined; I want to the user to download his own dataset.
I am getting the following error:
Error in lapply(obj, function(val) { : object 'datasetInput' not found
I think somewhere I have to use an observeEvent function?
Here's a variant of server.R; use it with akrun's ui.R. This one dynamically adapts the filtering choices, and allows you to add columns back by adding their column name even after clicking the button.
library(shiny)
library(DT)
server <- function(session, input, output) {
data <- reactive({
req(input$dataset)
read.csv(input$dataset$datapath, header = input$header,sep = input$sep)
})
filtereddata <- eventReactive({
input$update
data()
}, {
req(data())
if(is.null(input$select) || input$select == "")
data() else
data()[, colnames(data()) %in% input$select]
})
observeEvent(data(), {
updateSelectInput(session, "select", choices=colnames(data()))
})
output$mytable <- renderDataTable(filtereddata())
}
We could modify it
library(shiny)
library(DT)
-ui
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
fileInput("dataset", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
# Include clarifying text ----
#helpText(em("Note: This app requires file in csv format only!!")),
helpText(em("Note:Select all the inputs and click on button as given below to exectute the app")),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
selectInput("select", "Select columns to display", c('col1', 'col2'), multiple = TRUE),
actionButton("update", "Update Data set", class = "btn-primary",style='padding:4px; font-size:120%')
),
# Show a plot of the generated distribution
mainPanel(
h2('The Mydata'),
#tableOutput("mytable")
DT::dataTableOutput("mytable")
)
)
)
-server
server <- function(input, output) {
values <- reactiveValues(df_data = NULL)
observeEvent(input$dataset, {
values$df_data <- read.csv(input$dataset$datapath,
header = input$header,
sep = input$sep
)}
)
observeEvent(input$update, {
temp <- values$df_data[input$select]
values$df_data <- temp
})
output$mytable <- renderDataTable(values$df_data)
}
-Run the application
shinyApp(ui = ui, server = server)
-output
-after updating
#Christoph Wolk.....excellent it Worked!
Just a small change....since i do not want to show the data as soon it is selected using browse but only when update data set button is clicked i commented out outdata() as below"
filtereddata <- eventReactive({
input$update
#data()
}, {
req(data())
if(is.null(input$select) || input$select == "")
data() else
data()[, colnames(data()) %in% input$select]
})
observeEvent(data(), {
updateSelectInput(session, "select", choices=colnames(data()))
})
Is there a way to show a custom message instead of blank in the main panel when the app is opened ;something like this:
Please select a data set in csv format only
Somewhere we need to put some sort of condition i suppose in above filtereddata() :
validate(need(input$dataset != "","Please select a data set in csv format only!!!"))# custom error message on opening the app
Solved it!!!!!
filtereddata <- eventReactive({
validate(need(input$dataset != "","Please select a data set in csv format only!!!"))# custom error message on opening the app
input$update
#data()
}, {
req(data())
if(is.null(input$select) || input$select == "")
data() else
data()[, colnames(data()) %in% input$select]
})
in ui
add this to get custom colour for the error msg
# Custom error message with green colour ----
tags$head(
tags$style(HTML("
.shiny-output-error-validation {
color: green;
}
")))