R Shiny problem to pass reactive input to another function after plotting - r

I am new user of R Shiny and I have got a problem with passing reactive input to another function after plotting this reactive input.
In short, I want to create application which allow user to upload csv file, then choose x and y variables, plot these variables and then calculate area under curve of this plot. I could do everything except the last point. Plotting is fine, so I could pass reactive input to ggplot, but I could not pass it further to AUC function. Code line 126-129, at the end of coding. I know it is something very stupid which is missing, but now I am really stack. Tried different things, different wrong messages. Now it is: argument 1 is not a vector. I could run AUC is will make hard input of variables names such as AUC(data()$time, data()$response, method ="spline"), but I could not pass into AUC function user input for some reason.
Sorry for the stupid question.
Thank you for the help.
Here is the whole code.
library(shiny)
library(ggplot2)
library(dplyr)
library(tidyverse)
library(DescTools)
library(pROC)
library(shinythemes)
ui <- shinyUI(fluidPage(
titlePanel("Column Plot"),
tabsetPanel(
tabPanel("Upload File",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
tags$br(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
';'),
radioButtons('quote', 'Quote',
c(None='',
'Double Quote'='"',
'Single Quote'="'"),
'"')
),
mainPanel(
tableOutput('contents')
)
)
),
tabPanel("Plot",
pageWithSidebar(
headerPanel('My Plot'),
sidebarPanel(
# "Empty inputs" - they will be updated after the data is uploaded
selectInput("xcol", "X Variable", ""),
selectInput("ycol", "Y Variable", "", selected = "")
),
mainPanel(
plotOutput("MyPlot")
)
),
######
h4("Area under curve"),
textOutput("AUC")
)
)
)
)
server <- shinyServer(function(input, output, session) {
# added "session" because updateSelectInput requires it
data <- reactive({
req(input$file1) ## ?req # require that the input is available
inFile <- input$file1
df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
quote = input$quote)
# Update inputs (you could create an observer with both updateSel...)
updateSelectInput(session, inputId = "xcol", label = "X Variable",
choices = names(df), selected = names(df))
updateSelectInput(session, inputId = "ycol", label = "Y Variable",
choices = names(df), selected = names(df)[2])
return(df)
})
output$contents <- renderTable({
data()
})
output$MyPlot <- renderPlot({
x <- req(input$xcol)
y <- req(input$ycol)
p <- ggplot(data(), aes_string(x = x, y = y)) + geom_point(color="blue", size =7)
plot(p)
############
# Here is the problem, I can not pass x and y to the AUC function to calculate area under curve
# for the user input
output$AUC <- renderText({
AUC <- AUC(data()$x, data()$y, method ="spline")
})
#######################
})
})
shinyApp(ui, server)

The problem is that you call the columns x and y in your function AOC but these columns are only defined in your renderPlot, not in the whole server.
Replacing x and y by input$xcol and input$ycol (and using [[ ]]) allows to compute the area under the curve.
Corrected example below:
library(shiny)
library(ggplot2)
library(dplyr)
library(tidyverse)
library(DescTools)
library(pROC)
library(shinythemes)
ui <- shinyUI(fluidPage(
titlePanel("Column Plot"),
tabsetPanel(
tabPanel("Upload File",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
tags$br(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
';'),
radioButtons('quote', 'Quote',
c(None='',
'Double Quote'='"',
'Single Quote'="'"),
'"')
),
mainPanel(
tableOutput('contents')
)
)
),
tabPanel("Plot",
pageWithSidebar(
headerPanel('My Plot'),
sidebarPanel(
# "Empty inputs" - they will be updated after the data is uploaded
selectInput("xcol", "X Variable", ""),
selectInput("ycol", "Y Variable", "", selected = "")
),
mainPanel(
plotOutput("MyPlot")
)
),
######
h4("Area under curve"),
textOutput("AUC")
)
)
)
)
server <- shinyServer(function(input, output, session) {
# added "session" because updateSelectInput requires it
data <- reactive({
req(input$file1) ## ?req # require that the input is available
inFile <- input$file1
df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
quote = input$quote)
# Update inputs (you could create an observer with both updateSel...)
updateSelectInput(session, inputId = "xcol", label = "X Variable",
choices = names(df), selected = names(df))
updateSelectInput(session, inputId = "ycol", label = "Y Variable",
choices = names(df), selected = names(df)[2])
return(df)
})
output$contents <- renderTable({
data()
})
output$MyPlot <- renderPlot({
x <- req(input$xcol)
y <- req(input$ycol)
p <- ggplot(data(), aes_string(x = x, y = y)) + geom_point(color="blue", size =7)
plot(p)
############
# Here is the problem, I can not pass x and y to the AUC function to calculate area under curve
# for the user input
output$AUC <- renderText({
AUC(data()[[input$xcol]], data()[[input$ycol]], method ="spline")
})
#######################
})
})
shinyApp(ui, server)
Edit: you may have an error
Error: maximum number of subdivisions reached
but I suppose this is due to the function AOC.

Related

How can I set variable x as default when I upload a .CSV file on my App?

My Shiny Application's purpose is to upload a .csv file and plot a ggplot graph with its data.
When I upload a .csv file on my Shiny Application, the default variable is "y" for both input variables. However, when I change "y" to "x" on the "X Variable" input, the App works fine.
I just have to set "x" for "X Variable" input and "y" for "Y Variable" input as default when I upload the .csv file.
Here follows the app.R code with my comments and Error Message I get when I upload the file.
library(shiny)
library(datasets)
library(ggplot2)
ui <- shinyUI(fluidPage(
titlePanel("Column Plot"),
tabsetPanel(
tabPanel("Upload File",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
tags$br(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
selectInput('xcol', 'X Variable', "", selected = NULL),
selectInput('ycol', 'Y Variable', "", selected = NULL)
),
mainPanel(
tableOutput('contents'),
plotOutput('MyPlot')
)
)
)
)
)
)
server <- shinyServer(function(input, output, session) {
data <- reactive({
req(input$file1)
inFile <- input$file1
df <- read.csv(inFile$datapath, header = input$header, sep = input$sep)
## Update inputs
## I've already tried to change the selected = names(df) to selected = NULL on this part of the server code, but it didn't work.
updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
choices = names(df), selected = names(df))
updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
choices = names(df), selected = names(df)[2])
return(df)
})
output$contents <- renderTable({
data()
})
output$MyPlot <- renderPlot({
xy <- data()[, c(input$xcol, input$ycol)]
ggplot(data = xy, aes(x, y)) +
geom_line() +
geom_point()
})
})
shinyApp(ui, server)
The error message I get is:
"Error: object 'x' not found".
and welcome to SO 🤘
Your issue here is that you update the selectInput() at the wrong time: the update is done once the server has finished computing, so here once the data() is done running.
So to be clear, you update your input after trying to select from it.
Other thing is that you need to sym() & !! the input$ to make it work with ggplot() (see : https://github.com/ColinFay/tidytuesday201942/blob/master/R/mod_dataviz.R#L184 for example)
Here is a working version:
library(shiny)
library(datasets)
library(ggplot2)
library(rlang)
ui <- shinyUI(fluidPage(
titlePanel("Column Plot"),
tabsetPanel(
tabPanel("Upload File",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
tags$br(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
selectInput('xcol', 'X Variable', "", selected = NULL),
selectInput('ycol', 'Y Variable', "", selected = NULL)
),
mainPanel(
tableOutput('contents'),
plotOutput('MyPlot')
)
)
)
)
)
)
server <- shinyServer(function(input, output, session) {
r <- reactiveValues(
df = NULL
)
observe({
req(input$file1$datapath)
# req(input$xcol)
# req(input$ycol)
r$df <- read.csv(
input$file1$datapath,
header = input$header,
sep = input$sep
)
})
observeEvent( r$df , {
updateSelectInput(
session,
inputId = 'xcol',
label = 'X Variable',
choices = names(r$df),
selected = names(r$df)[1]
)
updateSelectInput(
session,
inputId = 'ycol',
label = 'Y Variable',
choices = names(r$df),
selected = names(r$df)[2]
)
}, ignoreInit = TRUE)
output$contents <- renderTable({
req(r$df)
head(r$df)
})
output$MyPlot <- renderPlot({
req(r$df)
req(input$xcol)
req(input$ycol)
ggplot(
data = r$df,
aes(!!sym(input$xcol), !!sym(input$ycol))
) +
geom_line() +
geom_point()
})
})
shinyApp(ui, server)

How to import a csv, makes it reactive and create plots

I'm trying to create a shiny app that imports different csv's and create plots using for example the package pROC.
library(shiny)
library(datasets)
ui <- shinyUI(fluidPage(
titlePanel("Column Plot"),
tabsetPanel(
tabPanel("Upload File",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
tags$br(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
radioButtons('quote', 'Quote',
c(None='',
'Double Quote'='"',
'Single Quote'="'"),
'"')
),
mainPanel(
tableOutput('contents')
)
)
),
tabPanel("First Type",
pageWithSidebar(
headerPanel('My First Plot'),
sidebarPanel(
selectInput('xcol', 'X Variable', ""),
selectInput('ycol', 'Y Variable', "", selected = "")
),
mainPanel(
plotOutput('MyPlot')
)
)
)
)
)
)
server <- shinyServer(function(input, output, session) {
data <- reactive({
req(input$file1)
inFile <- input$file1
df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
quote = input$quote)
updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
choices = names(df), selected = names(df))
updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
choices = names(df), selected = names(df)[2])
return(df)
})
output$contents <- renderTable({
data()
})
output$MyPlot <- renderPlot({
x <- data()[, c(input$xcol, input$ycol)]
pROC::roc(input$xcol,input$ycol)
})
})
shinyApp(ui, server)
I have tried to use different codes available in blogs, however, I did not find anything similar. It is possible to reproduce simple plots, like histograms but when I try to import the package proc for example there are always errors associated in this case: 'response' must have two levels
The input variable that you get in the server lists the column names in xcol and ycol. pROC's roc function expects the data itself, which you need to get from your data like for instance:
pROC::roc(x[[input$xcol]], x[[input$ycol]])

Conditional Display of Plots in Shiny

I'm trying to create a shiny app that allows user to display the kind of plot they want to show.
I've tried using a simple if else statement for the display of plot, however, it does not seem to work.
Is it because of my reactive function?
library(shiny)
library(ggplot2)
library(shinyjs)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("File to Plot"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
# Input: Select a file ----
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
# Horizontal line ----
tags$hr(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
radioButtons('quote', 'Quote',
c(None='',
'Double Quote'='"',
'Single Quote'="'"),
'"'),
#implementing dropdown column
selectInput('xcol', 'X Variable', ""),
selectInput('ycol', 'Y Variable', "", selected = ""),
selectInput('color', 'Colour', "", selected = ""),
tags$hr(),
checkboxGroupInput("my_choices", "Plots to Display",
choices = c("Scatterplot", "CorrMat"), selected = "Scatterplot")
),
# Show a plot of the generated distribution
mainPanel(
# Output: Data file ----
plotOutput('Scatterplot'), #need to add in more plots into the UI
plotOutput('CorrMat')
)
)
)
# Define server logic
server <- function(input, output, session) {
# added "session" because updateSelectInput requires it
data <- reactive({
req(input$file1) ## ?req # require that the input is available
inFile <- input$file1
# tested with a following dataset: write.csv(mtcars, "mtcars.csv")
# and write.csv(iris, "iris.csv")
df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
quote = input$quote)
updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
choices = names(df), selected = names(df))
updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
choices = names(df), selected = names(df)[2])
updateSelectInput(session, inputId = 'color', label = 'Colour',
choices = names(df), selected = names(df)[3])
return(df)
})
# hide plots on start
hide("Scatterplot");hide("CorrMat")
output$Scatterplot <- renderPlot({
ggplot(data = data(), aes_string(x = input$xcol, y = input$ycol, colour = input$color)) +
geom_point() +
theme_bw()
})
output$CorrMat <- renderPlot({
ggplot(data = data(), aes_string(x = input$xcol, y = input$ycol, colour = input$color)) +
geom_point() +
theme_bw()
})
observeEvent(input$my_choices,{
if(is.null(input$my_choices)){
hide("Scatterplot"); hide("CorrMat")
}
else if(length(input$my_choices) == 1){
if(input$my_choices == "Scatterplot"){
show("Scatterplot");hide("CorrMat")
}
if(input$my_choices == "CorrMat"){
hide("Scatterplot");show("CorrMat")
}
}
else{
if(all(c("Scatterplot","CorrMat") %in% input$my_choices)){
show("Scatterplot");show("CorrMat")
}
}
},ignoreNULL = F)
}
shinyApp(ui, server)
The code above is reproducible with any .csv file. Thank you so much!
Your code is sound. You just need to include this in the beginning of your ui:
ui <- fluidPage(
useShinyjs(), # add this
# rest of your ui code
)

Using Reactive Expressions

I am trying to use the user selected variable inputs after uploading any .csv file into the app, and plot a simple scatter plot.
Error: Reading objects from shinyoutput object not allowed.
I understand that I'm supposed to add in the reactive function, however I do not know where to add it. Could someone please share with me? Thank you!
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Javier Test"),
# Sidebar with a slider input for number of bins
sidebarLayout(
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"),
#implementing dropdown column
uiOutput("input1"), #use this instead when you are trying to upload something instead then process it
uiOutput("input2"),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
# Output: Data file ----
plotOutput("distPlot"),
plotOutput("scatterplot")
)
)
)
library(ggplot2)
# Define server logic required to draw a histogram
server <- function(input, output) {
#df <- reactiveValues(x= list, y = data.frame())
output$input1 <- renderUI({
selectInput("variable", "Variable:",
colnames(input$file1)) #this will select
})
output$input2 <- renderUI({
selectInput("variable1", "Variable:",
colnames(input$file1)) #this will select
})
# output$distPlot <- renderPlot({
#
# # obtain input from user for column
# x <- output$contents[, input1$variable] #selecting which column position
#
# # generate bins based on input$bins from ui.R
# bins <- seq(min(x), max(x), length.out = input$bins + 1)
#
# # draw the histogram with the specified number of bins
# hist(x, breaks = bins, col = 'darkgray', border = 'white')
#
# })
output$scatterplot <- renderPlot({
x <- output$contents[, input$variable]
y <- output$contents[, input$variable1]
#generate plot
ggplot(output$contents, aes(x=x, y=y, colour=Species)) + geom_point() + theme_classic()
})
}
shinyApp(ui, server)
Update
I've gotten it to work. Solution is below.
library(shiny)
library(ggplot2)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Javier Test"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
# Input: Select a file ----
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
# Horizontal line ----
tags$hr(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
radioButtons('quote', 'Quote',
c(None='',
'Double Quote'='"',
'Single Quote'="'"),
'"'),
#implementing dropdown column
selectInput('xcol', 'X Variable', ""),
selectInput('ycol', 'Y Variable', "", selected = "")),
# Show a plot of the generated distribution
mainPanel(
# Output: Data file ----
plotOutput('MyPlot')
)
)
)
# Define server logic required to draw a histogram
server <- shinyServer(function(input, output, session) {
# added "session" because updateSelectInput requires it
data <- reactive({
req(input$file1) ## ?req # require that the input is available
inFile <- input$file1
# tested with a following dataset: write.csv(mtcars, "mtcars.csv")
# and write.csv(iris, "iris.csv")
df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
quote = input$quote)
# Update inputs (you could create an observer with both updateSel...)
# You can also constraint your choices. If you wanted select only numeric
# variables you could set "choices = sapply(df, is.numeric)"
# It depends on what do you want to do later on.
updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
choices = names(df), selected = names(df))
updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
choices = names(df), selected = names(df)[2])
return(df)
})
output$MyPlot <- renderPlot({
x <- data()[,c(input$xcol, input$ycol)]
plot(x)
})
})
shinyApp(ui, server)

Create a ShinyApp to draw scatterplots using ggplot

I want to create a shiny app to draw scatterplots by selecting the variables in the uploaded data set to shiny app. I want to create plots using ggplot and plotly. The code I tried is as follow. But my app does not give the plot.
library(shiny)
library(datasets)
library(plotly)
ui <- shinyUI(fluidPage(
titlePanel("Column Plot"),
tabsetPanel(
tabPanel("Upload File",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv')),
tags$br(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
radioButtons('quote', 'Quote',
c(None='',
'Double Quote'='"',
'Single Quote'="'"),
'"')
),
mainPanel(
tableOutput('contents')
)
)
),
tabPanel("First Type",
pageWithSidebar(
headerPanel('My First Plot'),
sidebarPanel(
# "Empty inputs" - they will be updated after the data is uploaded
selectInput('xcol', 'X Variable', ""),
selectInput('ycol', 'Y Variable', "", selected = "")
),
mainPanel(
plotOutput('MyPlot')
)
)
)
)
)
)
server <- function(input, output, session) {
data <- reactive({
req(input$file1)
inFile <- input$file1
df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
quote = input$quote)
updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
choices = names(df), selected = names(df))
updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
choices = names(df), selected = names(df)[2])
return(df)
})
output$contents <- renderTable({
data()
})
output$trendPlot <- renderPlotly({
# build graph with ggplot syntax
p <- ggplot(data(), aes_string(x = input$xcol, y = input$ycol)) + geom_point()
ggplotly(p)
})
}
shinyApp(ui, server)
In the above code, the following section doesn't seem to work.
output$trendPlot <- renderPlotly({
# build graph with ggplot syntax
p <- ggplot(data(), aes_string(x = input$xcol, y = input$ycol)) + geom_point()
ggplotly(p)
})
Actually the problem is not in output$trendPlot but in mainPanel(...)
1 : Look closely, in mainPanel, you're calling plotOutput('MyPlot') but output$MyPlot doesn't exist, only plot that exists is output$trendPlot.
2 : Note output$trendPlot <- renderPlotly({...}), return type of trendPlot is renderPlotly but plotOutput is being called at main.
So, fix is
mainPanel(
plotlyOutput('trendPlot')
)
After fixing this, output is as follows :

Resources