using drop down bottom in shiny to loaed files from a folder - r

I am using shiny to upload different data files from a certain folder and plot a histogram based on a certain column. The name of each file looks like "30092017ARB.csv" (date + ARB.csv).
The code loops over all file names in the data-folder and print the name of files in a drop-down bottom. After selecting the name of file it should be uploaded and plot a histogram of the mw-column (the name of column is "mw). My GUI looks as follows:
library("shiny")
dataset <- list.files("C:/R_myfirstT/data", pattern=".*.csv$")
# Define UI for dataset viewer app ----
ui <- fluidPage(
# App title ----
titlePanel("Data plot"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Selector for choosing dataset ----
selectInput(inputId = "date",
label = "Choose a date:",
choices = dataset)
),
# Main panel for displaying outputs ----
mainPanel(
plotOutput("plot")
)
)
)
and the server
# Define server ----
dataset <- list.files("C:/R_myfirstT/data", pattern=".*.csv$")
dat.name<-paste("C:/R_myfirstT/data/",dataset,sep = "")
server <- function(input, output) {
datasetInput <- reactive({
switch(input$dataset,
for (i in 1:length(dataset)){
toString(dataset[i])=read.csv(file=dat.name[i], header=TRUE, sep=";")
}
)
output$plot <- renderPlot({
hist(dataset.mw, breaks = 40)
})
})
}
My problem is: I do not get any histogram! I get just the which is nice however, not entirely my goal!
Any idea what could be the reason?

Something like this works:
ui.R
library("shiny")
# Define UI for dataset viewer app ----
ui <- fluidPage(
# App title ----
titlePanel("Data plot"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Selector for choosing dataset ----
selectInput(inputId = 'date',
label = 'Choose a date:',
choices = list.files(path = "./data",
full.names = FALSE,
recursive = FALSE))
),
# Main panel for displaying outputs ----
mainPanel(
plotOutput("plot")
)
)
)
server.R
# Define server ----
server <- function(input, output) {
dataset <- reactive({
infile <- input$date
if (is.null(infile)){
return(NULL)
}
read.csv(paste0('./data/',infile))
})
output$plot <- renderPlot({
x <- dataset()[,1]
hist(x, breaks = 40)
})
}

Related

R Shiny allow user to select one or multiple datasets to download

I am new to R shiny and I hope someone can please guide me in the right direction.
I want the user to be able to select one or multiple datasets to download.
Code works when I put the multiple=F in selectInput but when I change it to TRUE, I get the error below:
"Warning: Error in switch: EXPR must be a length 1 vector"
Any help will be greatly appreciated as I am stuck on this for days.
Thank you
library(shiny)
library(openxlsx)
# Define UI for data download app ----
ui <- fluidPage(
# App title ----
titlePanel("Downloading Data"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Choose dataset ----
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars"), multiple=T),
# Button
downloadButton("downloadData", "Download")
),
# Main panel for displaying outputs ----
mainPanel(
tableOutput("table")
)
)
)
# Define server logic to display and download selected file ----
server <- function(input, output) {
# Reactive value for selected dataset ----
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})
# Table of selected dataset ----
output$table <- renderTable({
datasetInput()
})
# Downloadable xlsx of selected dataset ----
output$downloadData <- downloadHandler(
filename = function() {
"selected.xlsx"
},
content = function(filename) {
write.xlsx(datasetInput(), file = filename, rowNames = FALSE)
}
)
}
# Create Shiny app ----
shinyApp(ui, server)
In order to display several datasets, you can create a module (it is like creating a smaller shiny app inside your shiny app that you can call with parameters, just like a function). Here I created a module to display a table, with a dataframe as parameter.
For the download, I followed the link I gave you previously.
library(shiny)
#Using module
mod_export_table_ui <- function(id){
ns <- NS(id)
tagList(
tableOutput(ns("table_export"))
)
}
mod_export_table_server <- function(input, output, session, df_export){
ns <- session$ns
output$table_export <- renderTable({
df_export
})
}
# Define UI for data download app ----
ui <- fluidPage(
# App title ----
titlePanel("Downloading Data"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Choose dataset ----
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars"), multiple=T),
# Button
downloadButton("downloadData", "Download")
),
# Main panel for displaying outputs ----
mainPanel(
uiOutput("tables")
)
)
)
# Define server logic to display and download selected file ----
server <- function(input, output, session) {
rv <- reactiveValues()
#List of datasets
observeEvent(input$dataset, {
req(input$dataset)
rv$lst_datasets <- lapply(
1:length(input$dataset),
function(i) {
head(eval(parse(text =input$dataset[i])))
}
)
})
# Module UIs
output$tables <- renderUI({
req(rv$lst_datasets)
lapply(
1:length(rv$lst_datasets),
function(i) {
mod_export_table_ui(id = paste0("table", i))
}
)
})
# Module Servers
observeEvent(rv$lst_datasets, {
req(rv$lst_datasets)
lapply(
1:length(rv$lst_datasets),
function(i) {
callModule(
module = mod_export_table_server,
session = session,
id = paste0("table", i),
df_export = rv$lst_datasets[[i]]
)
}
)
})
output$downloadData <-downloadHandler(
filename = "Downloads.zip",
content = function(file){
withProgress(message = "Writing Files to Disk. Please wait...", {
temp <- setwd(tempdir())
on.exit(setwd(temp))
files <- c()
for(i in 1:length(rv$lst_datasets)){
writexl::write_xlsx(rv$lst_datasets[[i]],
path = paste0("dataset",i, ".xlsx")
)
files <- c(files, paste0("dataset",i, ".xlsx"))
}
zip(zipfile = file, files = files)
})
}
)
}
# Create Shiny app ----
shinyApp(ui, server)

How to calculate an mathematic expresion reciving values from sliders

I am new in Shiny and i am trying to learn. My issue is that i want to calculate an mathematic expresion by giving a value from slider and in the end to show the result. Until now i have made the following code but it is wrong. Could you please guide me.
Thanks in advance
library(shiny)
library(shinythemes)
# Define UI for slider demo app ----
ui <- fluidPage(
#Navbar structure for UI
navbarPage("SAR Model", theme = shinytheme("united"),
tabPanel("Toblers Function", fluid = TRUE),
# App title ----
titlePanel("Toblers Fuction"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar to demonstrate various slider options ----
sidebarPanel(
# Input: Slope interval with step value ----
sliderInput("slope", "Slope:",
min = -0.60, max = 0.50,
value = 0.0, step = 0.01),
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Table summarizing the values entered ----
tableOutput("values")
)
)
)
)
server <- function(input, output, session) {
# Reactive expression to create data frame off input value ----
sliderValues <- reactive({
data.frame(
Name = c("Slope"),
Value = as.character(c(input$slope)),
stringsAsFactors = FALSE)
})
Value$toblers <- 6*exp(-3.5*input$slope)
# Show the values in an HTML table ----
output$values <- renderTable({
sliderValues()
})
output$tobler <-renderText({value$toblers})
}
shinyApp(ui = ui, server = server)
You use input$slope outside of a reactive context which is not allowed. Define a reactive for your calculation of toblers and then display this, like:
toblers <- reactive({
6*exp(-3.5*input$slope)
})
output$tobler <-renderText({toblers()})
Ok i made some changes but does not show the result.
Here is the code
library(shiny)
library(shinythemes)
# Define UI for slider demo app ----
ui <- fluidPage(
#Navbar structure for UI
navbarPage("SAR Model", theme = shinytheme("united"),
tabPanel("Toblers Function", fluid = TRUE),
# App title ----
titlePanel("Toblers Fuction"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar to demonstrate various slider options ----
sidebarPanel(
# Input: Slope interval with step value ----
sliderInput("slope", "Slope:",
min = -0.60, max = 0.50,
value = 0.0, step = 0.01)),
# Main panel for displaying outputs ----
mainPanel(
# Output: Table summarizing the values entered ----
tableOutput("values"),
)
)
)
)
server <- function(input, output, session) {
# Reactive expression to create data frame off input value ----
sliderValues <- reactive({
data.frame(
Name = c("Slope"),
Value = as.character(c(input$slope)),
stringsAsFactors = TRUE)
})
# Show the values in an HTML table ----
output$values <- renderTable({
sliderValues()
})
output$slope <- renderText({
paste0("The speed is ", 6*exp(-3.5*input$slope),"Km/h")
})
}
shinyApp(ui = ui, server = server)
I found a solution but know does not appear the table with the value from slider.
Any opinion why?
here is the code
library(shiny)
library(shinythemes)
# Define UI for slider demo app ----
ui <- fluidPage(
#Navbar structure for UI
navbarPage("SAR Model", theme = shinytheme("united"),
tabPanel("Toblers Function", fluid = TRUE),
# App title ----
titlePanel("Toblers Fuction"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar to demonstrate various slider options ----
sidebarPanel(
# Input: Slope interval with step value ----
sliderInput("slope", "Slope:",
min = -0.60, max = 0.50,
value = 0.0, step = 0.01)),
# Main panel for displaying outputs ----
mainPanel(
# Output: Table summarizing the values entered ----
tableOutput("Values"),
tableOutput("slope")
)
)
)
)
server <- function(input, output, session) {
# Reactive expression to create data frame off input value ----
sliderValues <- reactive({
data.frame(
Name = c("Slope"),
Value = as.character(c(input$slope)),
stringsAsFactors = TRUE)
})
# Show the values in an HTML table ----
output$values <- renderTable({
sliderValues()
})
output$slope <- renderText({
paste0("The speed is ", 6*exp(-3.5*abs(input$slope+0.05)),"Km/h")
})
}
shinyApp(ui = ui, server = server)

Update checkboxGroupInput() choices after file upload

I have a simple shiny app below. In this app I want the user to be able to upload his own csv and then automatically this will be added as a choice in the checkbox group below the other dataset "D.B" (which I create in my original app).
#ui.r
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# 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")),
uiOutput("checkbox"),
textInput("filename","Set Filename")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
#server.r
server <- function(input, output) {
output$contents <- renderTable({
req(input$file1)
df <- read.csv(input$file1$datapath)
})
D.B <- reactive({
#some code that creates the dataset D.B.
})
output$checkbox<-renderUI({
checkboxGroupInput("datasetSelector","Specify the datasets to compare:", choices = c("D.B")
)
})
}
You could use a reactive value to store choices then add a choice everytime a file is uploaded. Use an observer to watch for file uploads (I also used the library rlist which gives me the append method).
library(rlist)
#ui.r
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# 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")),
uiOutput("checkbox"),
textInput("filename","Set Filename")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
#server.r
#fileOptions = list("D.B.")
server <- function(input, output, session) {
output$contents <- renderTable({
req(input$file1)
df <- read.csv(input$file1$datapath)
head(df)
})
fileOptions <- reactiveValues(currentOptions=c("D.B."))
observeEvent(input$file1, {
fileOptions$currentOptions = list.append(fileOptions$currentOptions, input$file1$datapath)
})
D.B <- reactive({
#some code that creates the dataset D.B.
})
output$checkbox<-renderUI({
checkboxGroupInput("datasetSelector","Specify the datasets to compare:", choices = fileOptions$currentOptions
)
})
}

How to process a file being uploaded and renamed in a shiny application

I have a simple shiny app below. In this app I want the user to be able to upload his own csv and then automatically this will be added as a choice in the checkbox group below the other dataset "D.B" (which I create in my original app). Then when the user chooses a file it will be displayed as a table.
Here I have managed to rename the uploaded file. However I can not then connect the renamed table with renderTable() while keeping the "changing name" ability.
# Define UI for data upload app ----
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# 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")),
checkboxGroupInput("datasetSelector","Data Files", choices=c("D.B")),
textInput("filename","Set Filename",value = "Set Name")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
#server.r
server <- function(input, output, session) {
observeEvent(input$filename, {
req(input$file1)
Name<-input$filename
updateCheckboxGroupInput(session,"datasetSelector", choices=c("D.B",Name))
})
observeEvent(input$file1, {
Data<-input$file1$datapath
Name<-input$filename
New <- read.csv(Data)
updateCheckboxGroupInput(session,"datasetSelector",
choices=c("D.B",input$file1$name))
})
D.B <- reactive({
if("D.B"%in% input$datasetSelector){
x <- read.csv("something.csv", stringsAsFactors = F)
}
})
output$contents <- renderTable({
New
})
}
Here is one solution.
This solution uses the ability of shiny inputs to take named lists. In a named list the label is the display name and the value is what is returned. E.g. c("a" = 1, "b" = 2) will display the labels a and b in the UI, but will return values of 1 and 2 in the server.
Because you want one of your labels to come from an input, it is necessary to build the ordered list in two parts. First, the values and then the labels. E.g. mylist = c(1,2) sets up the values then names(mylist) = c("a","b") assigns the labels.
Here is the code I had working:
library(shiny)
# Define UI for data upload app ----
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# 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")),
checkboxGroupInput("datasetSelector","Data Files", choices=c("D.B" = "original")),
textInput("filename","Set Filename",value = "Set Name")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
#server.r
server <- function(input, output, session) {
observeEvent(input$filename, {
req(input$file1)
Name<-input$filename
# make list
choices = c("original", "loaded")
# assign labels to list
names(choices) = c("D.B", Name)
updateCheckboxGroupInput(session,"datasetSelector", choices=choices)
})
observeEvent(input$file1, {
Data<-input$file1$datapath
Name<-input$filename
New <- read.csv(Data)
# make list
choices = c("original", "loaded")
# assign labels to list
names(choices) = c("D.B", Name)
updateCheckboxGroupInput(session,"datasetSelector", choices=choices)
})
D.B <- reactive({
if("D.B"%in% input$datasetSelector){
x <- read.csv("something.csv", stringsAsFactors = F)
}
})
output_table = reactive({
if("original" %in% input$datasetSelector)
return(D.B())
if("loaded" %in% input$datasetSelector)
return(read.csv(input$file1$datapath))
})
output$contents <- renderTable({
output_table()
})
}
# Run the app ----
shinyApp(ui = ui, server = server)

Multiple conditional selection criteria in shiny

Probably a simple one:
I have a data.frame such as this:
set.seed(1)
df <- data.frame(name=c("A","A","B","C","B","A"),id=1:6,rep1=rnorm(6),rep2=rnorm(6),rep3=rnorm(6))
In the UI part of the R shiny server I'd like to have a drop-down menu that lists unique(df$name), and then given that selection, in a second drop-down menu I'd like to list all df$id that correspond to that df$name selection (i.e., if the selected name is selected.name, this will be: dplyr::filter(df,name == selected.name)$id). Then given these two selections (which are a unique row in df) I'd like to execute server, which executes this function to plot the given selection:
plotData <- function(selected.df)
{
plot.df <- reshape2::melt(dplyr::select(selected.df,-name,-id))
ggplot2::ggplot(plot.df,ggplot2::aes(x=variable,y=value))+ggplot2::geom_point()+ggplot2::theme_minimal()
}
Here's the shiny code I'm trying:
server <- function(input, output)
{
output$id <- renderUI({
selectInput("id", "ID", choices = unique(dplyr::filter(df,name == input$name)$id))
})
output$plot <- renderPlot({
plotData(selected.df=dplyr::filter(df,name == input$name,id == output$id))
})
}
ui <- fluidPage(
# App title ----
titlePanel("Results Explorer"),
# Sidebar layout with a input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# select name
selectInput("name", "Name", choices = unique(df$name)),
uiOutput("id")
),
# Main panel for displaying outputs ----
mainPanel(
plotOutput("plot")
)
)
)
When I run: shinyApp(ui = ui, server = server), I get the error:
Evaluation error: Reading objects from shinyoutput object not allowed..
What's missing?
Here the option would be have renderUI in the 'server' and uiOuput in 'ui'
-ui
library(shiny)
library(dplyr)
library(ggplot2)
ui <- fluidPage(
# App title ----
titlePanel("Results Explorer"),
# Sidebar layout with a input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# select name
selectInput("name", "Name", choices = unique(df$name)),
uiOutput("idselection")
# select id - this is where I need help
),
# Main panel for displaying outputs ----
mainPanel(
# ShinyServer part
plotOutput("plot")
)
)
)
-server
server = function(input, output) {
output$idselection <- renderUI({
selectInput("id", "ID", choices = unique(df$id[df$name ==input$name]))
})
output$plot <- renderPlot({
df %>%
count(name) %>%
ggplot(., aes(x = name, y = n, fill = name)) +
geom_bar(stat = 'identity') +
theme_bw()
})
}
shinyApp(ui = ui, server = server)
-output
Ok, tiny fix:
Create data:
set.seed(1)
df <- data.frame(name=c("A","A","B","C","B","A"),id=1:6,rep1=rnorm(6),rep2=rnorm(6),rep3=rnorm(6))
Function that server will execute:
plotData <- function(selected.df)
{
plot.df <- reshape2::melt(dplyr::select(selected.df,-name,-id))
ggplot2::ggplot(plot.df,ggplot2::aes(x=variable,y=value))+ggplot2::geom_point()+ggplot2::theme_minimal()
}
shiny code:
server <- function(input, output)
{
output$id <- renderUI({
selectInput("id", "ID", choices = unique(dplyr::filter(df,name == input$name)$id))
})
output$plot <- renderPlot({
plotData(selected.df=dplyr::filter(df,name == input$name,id == input$id))
})
}
ui <- fluidPage(
# App title ----
titlePanel("Results Explorer"),
# Sidebar layout with a input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# select name
selectInput("name", "Name", choices = unique(df$name)),
uiOutput("id")
),
# Main panel for displaying outputs ----
mainPanel(
plotOutput("plot")
)
)
)

Resources