I'm trying to program a shiny app which reads your *.csv file and generates a plot out of this file. The file has a header and bottom containing several lines, which the user should be able to delete within the shiny app. So basically this edited file is the source for the plot.
I'm not sure how to create the reactive part based on the input file. Tried several approaches from this page, but i can't get it to work. I attached an simplified Test.csv file.
if (!require("shiny")) install.packages("shiny", dependencies = TRUE)
if (!require("shinyjs")) install.packages("shinyjs", dependencies = TRUE)
if (!require("DT")) install.packages("DT", dependencies = TRUE)
library(shiny)
library(shinyjs)
library(DT)
ui <- fluidPage(
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', FALSE),
radioButtons('sep', 'Separator', c(Semicolon=';', Comma=',', Tab='\t'), ','),
radioButtons('quote', 'Quote',c(None='', 'Double Quote'='"', 'Single Quote'="'"), '"'),
actionButton('delete_row', 'Delete row')
),
mainPanel(
DT::dataTableOutput('contents')
)
)
),
tabPanel("Plot",
pageWithSidebar(
headerPanel('Visualisation'),
sidebarPanel(
selectInput('xcol', 'X Variable', ""),
selectInput('ycol', 'Y Variable', "", selected = ""),
textOutput("m_out")
),
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)
})
### This part is the problem
###
observeEvent(input$delete_row, {
if (!is.null(input$contents_rows_selected)) {
#print(input$contents_rows_selected) #testing input
data$values <- data$values[-nrow(input$contents_rows_selected),]
}
})
###
### End of problem
output$contents = DT::renderDataTable({
data()
})
output$MyPlot <- renderPlot({
x <- data()[, c(input$xcol, input$ycol)]
plot(x)
})
}
### End of server commands
### Start Shiny App
shinyApp(ui = ui, server = server)
Thanks for your help in advance. Problem is marked with ###
Try making your data variable a reactiveVal(). I'd suggest also putting your input$file1 that reads-in the data frame.
In the server function:
data <- reactiveVal(NULL)
and to set its value into an event observing submitting the input file:
observeEvent(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])
data(df)
})
Deleting the row then would look something like:
...
df2 <- data()
df2 <- df2[-nrow(input$contents_rows_selected),]
data(df2)
...
This will allow your other UI functions to trigger when observing changes to the (reactive) data() object.
Related
Shinymeta is quite underutilized but extremely powerful. If you search "shinymeta" on Stackoverflow, you'll just get 9 results (not counting this one). The functionality captures the logic in the shiny and exposes it as code which then can be run outside the shiny. which ensures the reproducibility of the app.
So, my question is, how can we implement shinymeta in the basic shiny to capture the logic and expose it as code?
Thanks in advance.
library(shiny)
library(ggplot2)
library(datasets)
library(shinymeta)
ui <- shinyUI(fluidPage(
titlePanel("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 = ""),
actionButton("generateCode_1", label = "reproducibility!", icon = icon("code"),width=140)
),
mainPanel(
plotOutput('MyPlot', click = "plot_click",
hover = hoverOpts(id = "plot_hover", delayType = "throttle"),
brush = brushOpts(id = "plot_brush")),
hr(),
tableOutput("plot_brushedpoints"),
hr()
)
)
)
)
)
)
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({
graph <- ggplot(data(), aes(.data[[input$xcol]], .data[[input$ycol]])) +
geom_point(position='jitter')
graph
})
output$plot_brushedpoints <- renderTable({
df<- data()
res <- brushedPoints(df, input$plot_brush,
xvar = input$xcol,
yvar = input$ycol,
panelvar1 = NULL,
panelvar2 = NULL,
allRows = FALSE
)
if (nrow(res) == 0|is.null(res))
return(NULL)
res
})
observeEvent(input$generateCode_1, {
code <- expandChain(
quote({
print("The code should appear here ")
})
)
displayCodeModal(
code = code,
title = "Code for reproducibility"
)
})
})
shinyApp(ui, server)
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)
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]])
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 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 :