Hello everyone! my shiny app allows you to upload a file and get plots. My problem is that you only get the graphs if you select the right separator before loading the file. I would rather that it was possible to select the separator after loading the file and that the plots appear immediately after choosing the right separator, as is already the case for the table.
Thank you
This is my code:
library(shiny)
library(DT)
library(ggplot2)
library(tidyverse)
library(purrr)
library(dplyr)
library(shinythemes)
library(wesanderson)
library(reshape2)
library(colourpicker)
library(RColorBrewer)
library(shinyLP)
library(shinyjs)
# Define UI for data upload app ----
ui <- fluidPage(
theme = shinytheme("cerulean"),
sidebarLayout(
sidebarPanel(width=3,
conditionalPanel(
'input.dataset01=="Dataset"',
fileInput("file1", HTML('<h5><b>Choose File:</b></h5>'),
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
# Input: Checkbox if file has header
checkboxInput("header", "Header", TRUE),
# Input: Select separator
radioButtons("sep", HTML('<h5><b>Separator</b></h5>'),
choices = c(Semicolon = ";",
Comma = ",",
Tab = "\t"),
selected = "\t"),
# Input: Select number of rows to display
radioButtons("disp", HTML('<h5><b>Display</b></h5>'),
choices = c(All = "all",
Head = "head"),
selected = "all"),
# Select variables to display
uiOutput("checkbox1")),
conditionalPanel(
'input.dataset01 === "Statistical Distribution"',
# Input: Select what to display
selectInput("dataset1",HTML('<h5><b>Data:</b></h5>'),
choices =list(
uploaded_file = "inFile"),
selected=NULL),
uiOutput("plot.params2"),
radioButtons("plot.type", HTML('<h5><b>Plot Type:</b></h5>'),
list("Box Plot" = "boxplot", Histogram = "histogram")),
uiOutput("conditionalInput")
)),
# mainPanel
mainPanel(
tabsetPanel(
id = 'dataset01',
tabPanel("Dataset", h3(textOutput("caption1"), align="center"), DT::dataTableOutput("rendered_file1")),
tabPanel(("Statistical Distribution"), h3(textOutput("caption3"), align="center"),
plotOutput("p"))))
))
# Define server logic to read selected file ----
server <- function(input, output, session) {
# Read file 1 in Dataset
df1 <- reactive({
req(input$file1)
read.table(input$file1$datapath,
header = input$header,
sep = input$sep)
})
# Dynamically generate UI input when data is uploaded
output$checkbox1 <- renderUI({
checkboxGroupInput(inputId = "select_var1",
label = HTML('<h5><b>Select Variables</b></h5>'),
choices = names(df1()),
selected = names(df1()))
})
# Select columns to print
df1_sel <- reactive({
req(input$select_var1)
df1_sel <- df1() %>% select(input$select_var1)
})
# Print data table
output$rendered_file1 <- DT::renderDataTable({
if(input$disp == "head") {
head(df1_sel())
}
else {
df1_sel()
}
})
#plotting theme for ggplot2 global
.theme<- theme(
axis.line = element_line(colour = 'gray', size = .75),
panel.background = element_blank(),
plot.background = element_blank()
)
#Read in the uploaded data file and create a reactive variable called data_set
dataset1 <- reactive({if(is.null(input$file1)) return(NULL)
read.table(input$file1$datapath, header = TRUE, sep=input$sep)
})
output$plot.params2<- renderUI({
req(input$file1)
req(input$sep)
list(
fluidRow(selectInput(inputId = "variable", label = HTML('<h5><b>Variable:</b></h5>'), choices = names(dataset1()), selected = " ")),
fluidRow(selectInput(inputId = "group", label = HTML('<h5><b>Group:</b></h5>'), choices = names(dataset1()), selected = " "))
)})
output$caption3<-renderText({
req(input$file1)
switch(input$plot.type,
"boxplot" = " Box Plot",
"histogram" = "Histogram"
)
})
#get data object
get_data<-reactive({
req(input$file1)
if(!exists(input$dataset1)) return()
check<-function(x){is.null(x) || x==""}
if(check(input$dataset1)) return()
obj<-list(data=get(input$dataset1),
variable=input$variable,
group=input$group
)
#require all to be set to proceed
if(any(sapply(obj,check))) return()
#make sure choices had a chance to update
check<-function(obj){
!all(c(obj$variable,obj$group) %in% colnames(obj$data))
}
if(check(obj)) return()
obj
})
#plotting function using ggplot2
output$p <- renderPlot({
req(input$file1)
req(input$variable)
req(input$group)
plot.obj<-get_data()
#conditions for plotting
if(is.null(plot.obj)) return()
#make sure variable and group have loaded
if(plot.obj$variable == "" | plot.obj$group =="") return()
#plot types
plot.type<-switch(input$plot.type,
"boxplot" = list(geom_boxplot(),
scale_fill_manual(values=wes_palette(n=3, name="Moonrise3"))),
"histogram" = list(geom_histogram(alpha=0.8,position="identity"),
scale_fill_manual(values=wes_palette(n=3, name="Moonrise3")))
)
if(input$plot.type=="boxplot") { #control for 1D or 2D graphs
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$group,
y = plot.obj$variable,
fill = plot.obj$group # let type determine plotting
)
) + plot.type
if(input$show.points==TRUE)
{
p<-p+ geom_point(color='black',alpha=0.5, position = 'jitter')
}
} else {
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$variable,
fill = plot.obj$group,
group = plot.obj$group
)
) + plot.type
}
p<-p+labs(
fill = input$group,
x = "",
y = input$variable
)
.theme
print(p)
}, bg="transparent")
#show points only for boxplot
output$conditionalInput <- renderUI({
if(input$plot.type=="boxplot"){
checkboxInput("show.points", "show points", NULL)
}})
# set uploaded file
upload_data<-reactive({
req(input$file1)
req(input$sep)
inFile <- input$file1
if (is.null(inFile))
return(NULL)
#could also store in a reactiveValues
read.table(inFile$datapath,
header = TRUE,
sep = input$sep)
})
observeEvent(input$file1,{
inFile<<-upload_data()
})
}
# Create Shiny app ----
shinyApp(ui, server)