Shiny conditional panel - r

In my app I want the user to choose a folder, and the to choose a file from that folder.
I thought to use conditionalPanel() so the user will see only the first button until he pick's the folder. I wrote this code but I get this error message, 'object 'input' is not found', what would be the right way to do this? And is it a problem to put a conditional panel in an absolute panel?
library(shiny)
library(ggplot2)
ui <- shinyUI(fluidPage(
titlePanel(""),
fluidRow(
# select input for selecting a folder
column(2, absolutePanel(fixed = TRUE, width = '180px',
selectInput("pick_folder", label = '', selected='choose_a_folder',
choices = setNames(as.list(c('choose_a_folder', basename(setdiff(list.dirs(recursive = FALSE),'.')))),
c('choose_a_folder', basename(setdiff(list.dirs(recursive = FALSE),'.'))))))),
# select input for selecting a file absolutePanel then conditionalPanel
column(2, absolutePanel(fixed = TRUE, width = '180px',
conditionalPanel(condition="input.pick_folder==choose_a_folder",
selectInput('pick_file', label = '', selected = 'choose_a_file',
choices = setNames(as.list(c('choose_a_file', basename(setdiff(list.files(path=input$pick_folder ,recursive = FALSE),'.')))),
c('choose a file', basename(setdiff(list.files(path=input$pick_folder ,recursive = FALSE),'.')))))))),
),
fluidRow(
#plot
plotOutput('my_plot')
)))
# server
server <- shinyServer(function(input, output) {
output$my_plot <- renderPlot({
dat <- read.table(file=paste(input$pick_folder, input$pick_file, sep='/'))
# some plots over dat
})
})
shinyApp(ui, server)

The probem arises from trying to dynamically create the choices for the file selection inside the ui part of your app. The way you should do this is to create the dynamic part of the ui (Your file selection) in your server part using uiOutput and renderUI
The following code seems to do what you describe you want:
library(shiny)
library(ggplot2)
ui <- shinyUI(fluidPage(
titlePanel(""),
fluidRow(
# select input for selecting a folder
column(2, absolutePanel(fixed = TRUE, width = '180px',
selectInput("pick_folder", label = '', selected='choose_a_folder',
choices = setNames(as.list(c('choose_a_folder', basename(setdiff(list.dirs(recursive = FALSE),'.')))),
c('choose_a_folder', basename(setdiff(list.dirs(recursive = FALSE),'.'))))))),
# select input for selecting a file absolutePanel then conditionalPanel
column(2, absolutePanel(fixed = TRUE, width = '180px',
conditionalPanel(condition="input.pick_folder==choose_a_folder",
# Insert a dynamic bit of UI
uiOutput("fileselection")
)
)
)
),
fluidRow(
#plot
plotOutput('my_plot')
)))
# server
server <- shinyServer(function(input, output) {
output$my_plot <- renderPlot({
dat <- read.table(file=paste(input$pick_folder, input$pick_file, sep='/'))
# some plots over dat
})
output$fileselection <- renderUI({ #Define the dynamic UI
selectInput('pick_file', label = '', selected = 'choose_a_file',
choices = setNames(as.list(c('choose_a_file', basename(setdiff(list.files(path=input$pick_folder ,recursive = FALSE),'.')))),
c('choose a file', basename(setdiff(list.files(path=input$pick_folder ,recursive = FALSE),'.'))
)
)
)
})
})
shinyApp(ui, server)

Related

How to have a user input text and create a list with shiny? R

I have the following app which allows for text to be entered and it is then saved as VALUE and printed on a panel.
Although it looks like I can only do this with one text input at a time - even if I click add (so I don't believe this button is working). On top of that I would like for the user to be able to add multiple inputs (like I have below).
And then my VALUE function should be list with multiple inputs.
code below
library(shiny)
ui <- fluidPage(
headerPanel("R Package App"),
sidebarPanel(
# selectInput("options", "options", choices=c('abc','def')),
textInput("textbox", "Enter R Package Name", ""),
actionButton("add","Add")
),
mainPanel(
textOutput("caption")
)
)
server <- function(input, output, session) {
observe({
VALUE <- ''
if(input$add>0) {
isolate({
VALUE <- input$textbox
})
}
updateTextInput(session, inputId = "textbox", value = VALUE)
})
output$caption <- renderText({
input$textbox
})
}
shinyApp(ui = ui, server = server)
Have you considered using selectizeInput with it's create option?
library(shiny)
packagesDF <- as.data.frame(installed.packages())
ui <- fluidPage(
headerPanel("R Package App"),
sidebarPanel(
selectizeInput(
inputId = "selectedPackages",
label = "Enter R Package Name",
choices = packagesDF$Package,
selected = NULL,
multiple = TRUE,
width = "100%",
options = list(
'plugins' = list('remove_button'),
'create' = TRUE,
'persist' = TRUE
)
)
),
mainPanel(textOutput("caption"))
)
server <- function(input, output, session) {
output$caption <- renderText({
paste0(input$selectedPackages, collapse = ", ")
})
}
shinyApp(ui = ui, server = server)

Are there any specific resources to use for creating a shiny app that uploads a file and plots a selected column?

library(shiny)
library(plotly)
library(ggplot2)
library(tidyverse)
library(DT)
if (!require("okcupiddata")) install.packages("okcupiddata")
library(okcupiddata)
D=sample_n(profiles, 5000)
write.csv(D, file="~/Downloads/OKCupid.csv", row.names = FALSE)
ui <- fluidPage(
# Application title
titlePanel(title = "Uploading Your File"),
sidebarLayout(
sidebarPanel(
width = 2,
## Create a file upload control
fileInput(inputId = "file",
label = "Choose Your File:",
accept = c(".txt", ".csv")),
## Use html tag hr (horizontal rule) to make a horizontal separator
hr(),
## Make a h5 heading
h5("Max file size is 2M"),
## Create a checkbox that can be used to specify logical values.
checkboxInput(inputId = "header",
label = "Header",
value = TRUE),
## Create a set of radio buttons used to select an item from a list.
radioButtons(inputId = "sep",
label = "Separator",
choices = c(Comma = ",", Space = " ", Tab = "\t")),
uiOutput("variable")
),
mainPanel(
tabsetPanel(
tabPanel("Table", tableOutput("table")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Plot", plotlyOutput("plot", height = "700px"))
)
)
)
)
server <- function(input, output, session) {
myData <- reactive({
f = input$file
if (is.null(f)){
return(NULL)
} else {
read.table(f$datapath, header = input$header, sep = input$sep)
}
})
#A. Create a drop-down menu to choose a variable
output$variable <- renderUI({
})
#B. Display the whole table
output$table <- renderTable({
})
#C. Summarize the whole table
output$summary <- renderPrint({
})
#D. Plot only the selected variable.
# The code needs to handle both a categorical and numeric variables
output$plot <- renderPlotly({
})
}
shinyApp(ui = ui, server = server)
I'm stuck on A, B, C, and D. I know to use selectInput() to create a drop down menu, a data frame() function to render a table, a summary() function to render a summary, and a ggplot() function to render both a numeric and categorical plot.I don't know how to correctly reference the selected file and then reference the column from said file. Any ideas?
The answer completes A, B, C and D. You haven't really shared what kind of plot you need but based on class of the column selected this displays the plot.
library(shiny)
library(plotly)
library(tidyverse)
library(DT)
ui <- fluidPage(
# Application title
titlePanel(title = "Uploading Your File"),
sidebarLayout(
sidebarPanel(
width = 2,
## Create a file upload control
fileInput(inputId = "file",
label = "Choose Your File:",
accept = c(".txt", ".csv")),
## Use html tag hr (horizontal rule) to make a horizontal separator
hr(),
## Make a h5 heading
h5("Max file size is 2M"),
## Create a checkbox that can be used to specify logical values.
checkboxInput(inputId = "header",
label = "Header",
value = TRUE),
## Create a set of radio buttons used to select an item from a list.
radioButtons(inputId = "sep",
label = "Separator",
choices = c(Comma = ",", Space = " ", Tab = "\t")),
uiOutput("variable")
),
mainPanel(
tabsetPanel(
tabPanel("Table", tableOutput("table")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Plot", plotlyOutput("plot", height = "700px"))
)
)
)
)
server <- function(input, output, session) {
myData <- reactive({
f = input$file
if (is.null(f)){
return(NULL)
} else {
read.table(f$datapath, header = input$header, sep = input$sep)
}
})
#A. Create a drop-down menu to choose a variable
output$variable <- renderUI({
selectInput('dd', 'Select dropdown', names(myData()))
})
#B. Display the whole table
output$table <- renderTable({
myData()
})
#C. Summarize the whole table
output$summary <- renderPrint({
summary(myData())
})
#D. Plot only the selected variable.
# The code needs to handle both a categorical and numeric variables
output$plot <- renderPlotly({
if(is.numeric(myData()[[input$dd]]))
plt <- ggplot(myData(), aes(.data[[input$dd]])) + geom_histogram()
else
plt <- ggplot(myData(), aes(.data[[input$dd]])) + geom_bar()
ggplotly(plt)
})
}
shinyApp(ui = ui, server = server)

R-Shiny: Select input reactive on file input

I am very new to Shiny and am not sure if I am doing this remotely correct/completely oversimplified. I am trying to pull the column headers from an excel fileInput into a selectInput drop down box.
So essentially I would like the options for the select box be determined by the headers of the file input. Then it would link into my equation in the server, which would perform the calculation based on the dataset in the column (the bit in the server with input$col).
I appreciate any comments/answers,
Thanks
EDIT: at a guess, would I need to use uiOutput and renderUI??
ui
ui <- fluidPage(theme = shinytheme(),
setBackgroundColor("white"),
titlePanel(img(src = "image.png", height = 125, width = 450)),
(h1("review app", style = "color:#337ab7")),
p("Calculate"),
headerPanel(h3("Input data here", style = "color:#337ab7")),
sidebarLayout(
sidebarPanel( position =c("left"), style = "color:#337ab7",
numericInput("SL",
"SL", 1, min=1, max=10),
numericInput("LT", "LT",0, min=0, max = 52),
fileInput("file1", 'choose file',
accept = c(".xlsx") ),
selectInput("col", "Column", choices = unique(colnames(input$file1)
)),
checkboxInput("smooth", "Clean my data", value = FALSE, width = NULL),
actionButton("action_Calc", label = "Refresh & Calculate", icon("redo"),
style="color: #fff; background-color: #337ab7; border-color: #2e6da4"),
),
mainPanel(
tabsetPanel(
tabPanel("SS", h1(textOutput("SS"), style = "color:#337ab7")),
tabPanel("guide", img(src = "guide.png", height = 200, width = 600)),
tabPanel("Mydata", div(tableOutput('contents'), style="font-size:55%"))
))))
server
server <- function(input, output) {
Data <- reactive({
req(input$file1)
inFile <- input$file1
read_excel(inFile$datapath, 1)
})
output$contents <- renderTable(bordered = TRUE, style= "border-color:#337ab7", hover = TRUE, {
Data()
})
values<- reactiveValues()
observe({
input$action_Calc
values$int<- isolate({ if (input$smooth) (round( input$SL*sqrt(input$LT/4)*sd( tsclean(Data()[[input$col]],
replace.missing = TRUE, lambda = NULL)) , digits= 2))
else (round( input$SL*sqrt(input$LT/4)*sd(Data()[[input$col]]), digits = 2)) })})
output$SS <- renderText({paste("Calculated is", values$int)} )
}
shinyApp(ui, server)
updatedSelectInput should do it for you. Below is a minimal example.
To reduce package dependencies I switched to loading .csv rather than .xlsx. Note that the loaded file isn't validated, so if junk goes in you'll get junk out.
library(shiny)
#UI
ui <- fluidPage(
selectInput('mydropdown', label = 'Select', choices = 'No choices here yet'),
fileInput('myfileinput', label = 'Select File', accept = c(".csv"))
)
#Server
server <- function(input, output, session) {
observeEvent(input$myfileinput, {
mytable <- read.csv(input$myfileinput$datapath)
updateSelectInput(session, "mydropdown", label = "Select", choices = colnames(mytable))
})
}
shinyApp(ui = ui, server = server)

Plot data after browsing input files with Shiny

I am trying to build a Shiny App that does the following:
1) Browse a value file that looks like
Sample x y
A 1 3
B 2 1
C 3 6
D 4 4
2) Browse a second info file,
Sample Country Status
A US OK
B UK OK
C UK NOPE
D US OK
3) When I press a Submit button,
4) I merge the two files by the Sample column,
5) And make a scatter plot with ggplot, with a dropdown menu that allows me to color the points according to the names of the columns from the info file.
With the code below, I am facing two problems: (i) after I load my files and press the Submit button, nothing happens, and (ii) how could I mention in my selectInput block for my dropdown menu the number of possible choices (assuming I do not know them in advance)?
library(shiny)
library(ggplot2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput(
inputId = "user_value_file",
label = "Choose a file with numeric values"
),
fileInput(
inputId = "user_info_file",
label = "Choose a file with sample info"
),
actionButton(
inputId = "my_button",
label = "Submit"
)
),
mainPanel(
# browse sample annotation file
selectInput(
inputId = "info_col",
label = "Choose an info to color",
choices = c("Country", "Status") # I am cheating here because I know in advance what are the colnames of the info file
),
# outputs
plotOutput(
outputId = "my_scatter_plot"
)
)
)
)
server <- function(input, output) {
output$contents <- renderTable(
{
valueFile <- input$user_value_file
if (is.null(valueFile))
return(NULL)
infoFile <- input$user_info_file
if (is.null(infoFile))
return(NULL)
}
)
randomVals <- eventReactive(
input$goButton,
{
my_val <- read.table(valueFile$datapath, header = T, sep = "\t")
my_info <- read.table(infoFile$datapath, header = T, sep = "\t")
df <- merge(my_val, my_info, by="Sample")
output$my_scatter_plot <- renderPlot(
{
ggplot(df, aes_string(x=df$x, y=df$y, color=input$info_col)) +
geom_point()
}
)
}
)
}
shinyApp(ui = ui, server = server)
A few things noted to get it working:
the inputID in the layout needs to match the server renderTable parameters (e.g., input$goButton should be input$my_button)
renderPlot was moved from eventReactive, and calls randomVals to get the data frame df
To get choices from the user info file, added session to server function and updateSelectInput (note depending on that file structure you probably want to do something like remove first column name or other changes)
Otherwise left things as they are. Please let me know if this has the behavior you were looking for.
library(shiny)
library(ggplot2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput(
inputId = "user_value_file",
label = "Choose a file with numeric values"
),
fileInput(
inputId = "user_info_file",
label = "Choose a file with sample info"
),
actionButton(
inputId = "my_button",
label = "Submit"
)
),
mainPanel(
# browse sample annotation file
selectInput(
inputId = "info_col",
label = "Choose an info to color",
choices = NULL # Get colnames from user_info_file later on
),
# outputs
plotOutput(
outputId = "my_scatter_plot"
)
)
)
)
server <- function(input, output, session) {
output$contents <- renderTable({
valueFile <- input$user_value_file
if (is.null(valueFile))
return(NULL)
infoFile <- input$user_info_file
if (is.null(infoFile))
return(NULL)
})
randomVals <- eventReactive(input$my_button, {
my_val <- read.table(input$user_value_file$datapath, header = T, sep = "\t")
my_info <- read.table(input$user_info_file$datapath, header = T, sep = "\t")
updateSelectInput(session, "info_col", "Choose an info to color", choices = names(my_info)[-1])
merge(my_val, my_info, by="Sample")
})
output$my_scatter_plot <- renderPlot({
df <- randomVals()
ggplot(df, aes_string(x=df$x, y=df$y, color=input$info_col)) +
geom_point()
})
}
shinyApp(ui, server)

Creating R-shiny app, want to use the names of people in CSV file as choices in selectInput

Not sure if this has been asked before. I am very new to working with RShiny apps, and I would like to use the values from a particular column of a particular CSV file for the choices in my selectInput() select box. Here is my code without the CSV, using some dummy variables.
ui <- shinyUI(fluidPage(
titlePanel(title = h4("PLAYER SELF-CENTERED RATING (PSCR)", align = "center")),
sidebarLayout(
sidebarPanel(
selectInput("selectplayer",
label = h3("Select box"),
choices = list("Choice 1" = 3,
"Choice 2" = 4,
"Choice 3" = 5),
selected = 3)
),
mainPanel(
plotOutput('radarPlot', width = "100%")
)
)
))
quite frankly, I'm fairly lost w.r.t where to begin on this. I also will need to use data from the CSV file to create another dataframe that is plotted in a renderPlot() call in shinyServer, so will need to find a way to get the CSV data into both server and ui. Is this a simple task, or something difficult? any help appreciated!
You can display uiOutput in ui and dynamically generate the ui in server. The code below should give you a hint.
library(shiny)
server <- function(input, session, output) {
# read csv here
datin <- read.table(text = 'Name,Age,Weight
John,10,40
Hary,20,70
Mike,30,80',
header = TRUE, sep =",", stringsAsFactors = FALSE)
output$select_1 = renderUI({
selectInput("select_input","select", choices = datin['Name'])
})
}
ui <- fluidPage(
uiOutput("select_1")
)
shinyApp(ui = ui, server = server)
You can generate dynamic output using uiOutput in the sidebar as shown in the following code:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "R-shiny app"),
dashboardSidebar(
uiOutput("columnNames") # Dynamic generate UI element
),
dashboardBody(
fluidRow(
column(10,
dataTableOutput('dataview')) #Display data in the tabular form
),
fluidRow(column(3, verbatimTextOutput("column_value"))),
hr()
)
)
server <- function(input, output) {
# Read data from .csv file
data=iris # (for understanding I am using iris dataset)
output$column_value <- renderPrint({
output$columnNames <- renderUI({
selectInput("datacolumn", h4("Select Data Column"), colnames(data)) # Dynamically set selectInput
})
output$dataview <- renderDataTable(data,options = list(pageLength = 10)) # Display the iris dataset
})
}
shinyApp(ui, server)

Resources