I am trying to renderplot using ggplot2 instead of the base R's plot function.
However I've encountered some problems when using reactive dataset in ggplot2.
Below is the code that works with base R's plot:
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)
This is the part where I'm trying to change to ggplot2 render plot instead:
output$MyPlot <- renderPlot({
ggplot(data, aes(x=input$xcol, y=input$ycol)) + geom_point()
})
Error: ggplot2 doesn't know how to deal with data of class reactiveExpr/reactive
Any idea how do I use a reactive data set for ggplot2?
Thank you so much!
Update
Here's the code! I've figured it out. Not very nice, is there a better way to represent it?
output$MyPlot <- renderPlot({
x <- data()[,c(input$xcol, input$ycol)]
ggplot(x, aes(x=x[,1], y=x[,2])) + geom_point()
})
Instead of sub-setting the data multiple times in the renderPlot function, you could instead of using aes function you would use aes_string function from ggplot package. So the one liner solution will be:
output$MyPlot <- renderPlot({
ggplot(data = data(), aes_string(x = input$xcol, y = input$ycol)) + geom_point()
})
It works well now:
output$MyPlot <- renderPlot({
x <- data()[,c(input$xcol, input$ycol)]
ggplot(x, aes(x=data()[,c(input$xcol)],
y=data()[,c(input$ycol)])) + geom_point()
})
Related
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.
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
)
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)
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 :
I have the following problem, when executing my Shiny App.
What I am trying, is to plot a simple dataset in ggplot. Firstly whether geom_point() or geom_line() is not important, but the input data should be the csv data set and the x-axis should be adjusted by the date range.
My Problem now is, that the ggplot is empty after uploading the data:
and the warning message is the following:
Warning: Removed 8399 rows containing missing values (geom_point)
It doesn't appear when I replaced geom_point() by geom_line(), but the ggplot stays empty.
The full csv table can be downloaded here:
https://www.dropbox.com/s/xf7qtv7u2rcqdw9/sample_sales.csv?dl=0
The ui.R script is the following:
shinyUI(pageWithSidebar(
headerPanel("My App"),
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept = c('text/csv', 'text/comma-separated-values,text/plain', '.csv')),
tags$hr(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',
c(Comma = ',',
Semicolon = ';',
Tab = '\t'),
'Comma'),
radioButtons('quote', 'Quote',
c(None = '',
'Double Quote' = '"',
'Single Quote' = "'"),
'Double Quote'),
dateRangeInput("daterange", "Date range:",
start = "2009-01-01",
end = "2012-12-30")),
mainPanel(
tabsetPanel(
tabPanel("Sales", plotOutput("sales")),
tabPanel("Category", plotOutput("category")),
tabPanel("Table", tableOutput("contents")))
)
)
)
and the server.R script looks like this:
library(ggplot2)
library(shiny)
library(lubridate)
shinyServer(function(input, output) {
sales <- reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
read.csv(inFile$datapath, header = input$header, sep = input$sep, quote = input$quote)
})
range <- reactive({
c(input$daterange[1], input$daterange[2])
})
output$contents <- renderTable({
print(head(sales()))
})
output$sales <- renderPlot({
sales.df <- sales()
sales.df$Order.Date <- as.Date(sales.df$Order.Date, "%Y/%m/%d")
sales.df$Profit <- as.numeric(sales.df$Profit)
y.limit = c(min(sales.df$Profit), max(sales.df$Profit))
p <- ggplot(sales.df, aes(x = Order.Date, y = Profit)) + geom_point(size = 400) + scale_x_date(limits = c(input$daterange[1], input$daterange[2]))
print(p)
})
output$category <- renderPlot({
if (is.null(input$file1)) {
return()
}
print(plot(sales()$sales[16]))
})
})
I hope you can help me, thanks in advance