I was trying to simplify my shiny app. However, as much as I try it is not working, as I would like it to.
My Idea was to load data to the app, perform some analyses and return intermediate results to the user. At the moment I have to load the data, choose the right columns etc. for each output I am generating:
ui <- shinyServer(
fluidPage(
tabsetPanel(
tabPanel("Data upload",
titlePanel("Data upload"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",multiple = TRUE, accept = c("text/csv","text/comma-separated-values,text/plain",".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE), radioButtons("sep", "Separator", choices = c(Comma = ",", Semicolon = ";",Tab = "\t"), selected = ","),
tags$hr(),
checkboxInput("disp", "Display",TRUE),
tags$hr(),
uiOutput("choose_first_column"),
uiOutput("choose_second_column"),
br()
),
mainPanel(
tableOutput("contents"),
tags$hr(),
tableOutput("tab")
)
)
),
tabPanel("2","2"
)
)
)
)
server <- shinyServer(
function(input, output) {
observe({
req(input$file1)
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
output$contents <- renderTable({
(head(df))})
output$choose_first_column <- renderUI({
colnames <- names(df)
selectInput("column_1", "Choose Date column",
choices = colnames,
selected = colnames)})
output$choose_second_column <- renderUI({
colnames <- names(df)
selectInput("column_2", "Choose Variable column",
choices = colnames,
selected = colnames)})
output$tab <- renderTable({
req(input$file1)
df2 <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
df2 <- df2[, c(input$column_1,input$column_2), drop = FALSE]
return(head(df2))})
})
})
runApp(list(ui = ui, server = server))
It works, but as I usually have many data and I want to perform a couple of analyses, it is gets quite time-consuming to load and process the data for each “output content”.
Is there a way to avoid this? Could I for example load the data and choose the right columns globaly, as in the second example? (I crossed out the lines where the error occurs)
ui <- shinyServer(
fluidPage(
tabsetPanel(
tabPanel("Data upload",
titlePanel("Data upload"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",multiple = TRUE, accept = c("text/csv","text/comma-separated-values,text/plain",".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE), radioButtons("sep", "Separator", choices = c(Comma = ",", Semicolon = ";",Tab = "\t"), selected = ","),
tags$hr(),
checkboxInput("disp", "Display",TRUE),
tags$hr(),
uiOutput("choose_first_column"),
uiOutput("choose_second_column"),
br()
),
mainPanel(
tableOutput("contents"),
tags$hr(),
tableOutput("tab")
)
)
),
tabPanel("2","2"
)
)
)
)
server <- shinyServer(
function(input, output) {
observe({
req(input$file1)
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
output$contents <- renderTable({
(head(df))})
output$choose_first_column <- renderUI({
colnames <- names(df)
selectInput("column_1", "Choose Date column",
choices = colnames,
selected = colnames)})
output$choose_second_column <- renderUI({
colnames <- names(df)
selectInput("column_2", "Choose Variable column",
choices = colnames,
selected = colnames)})
# df <- df[, c(input$column_1,input$column_2), drop = FALSE]
#
# output$tab <- renderTable({
# (head(df))})
})
})
runApp(list(ui = ui, server = server))
Input data example:
date time level
01.01.2000 00:00:00 0.3724
01.01.2000 01:00:00 0.192
01.01.2000 02:00:00 -0.0252
I would appreciate any help!
Aishe
From what I've understood, you are getting an error because the dataframe df that you have defined is not reactive. You should make it reactive as it will change every time the user selects input columns.
Refer this to read about reactivity. Change the deleted portion of your code to this:
df.selected.columns <- df[c(input$column_1,input$column_2)]
output$tab <- renderTable({
(head(df.selected.columns()))
})
Related
The example that I'm working with is the iris data. If the current data contains iris[1:15,], how can I upload a .csv file with more iris data and click a button to combine the uploaded data with the current data and save everything in one dataframe?
Here is what I have so far based on what I've read. I was able to create the fileInput and action button but I think my issue is with the reactive button. I'm not sure how to use it properly to achieve what I need.
library(shiny)
library(DT)
data1<-data.frame(iris[1:15,])
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
numericInput('num','Number of rows',value=10,min=0),
actionButton("update", "Combine Data")),
mainPanel(
tableOutput("table")
)
)
)
server <- function(input, output) {
output$table <- renderTable({
head(data1,n=input$num)
})
x<-reactive({
req(input$file1)
df_uploaded <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote,
stringsAsFactors = FALSE)
data2<-data.frame(df_uploaded)
return(data2)
})
merged_data<-eventReactive(input$update,{
datam<-rbind.data.frame(data1,x())
return(datam)
})
# output$table <- renderTable({
# head(merged_data(),n=input$num)})
}
shinyApp(ui, server)
Thanks!
The main issue is that read.csv receiving invalid argument i.e. NULL for header, sep, quote as you don't have input$header, input$sep, input$quote in UI.
library(shiny)
library(DT)
data1<-data.frame(iris[1:15,])
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
numericInput('num','Number of rows',value=10,min=0),
actionButton("update", "Combine Data")),
mainPanel(
tableOutput("table")
)
)
)
server <- function(input, output) {
# output$table <- renderTable({
# head(data1,n=input$num)
# })
x<-reactive({
req(input$file1)
df_uploaded <- read.csv(input$file1$datapath,
#you don't have these variables in the UI, so they will raise an error
#header = input$header,
#sep = input$sep,
#quote = input$quote,
stringsAsFactors = FALSE)
#No need data2 and return(data2) as read.csv returns data.frame by default
#data2<-data.frame(df_uploaded)
#return(data2)
})
merged_data<-eventReactive(input$update,{
datam<-rbind.data.frame(data1, x())
return(datam)
})
output$table <- renderTable({
head(merged_data(), n=input$num)})
}
shinyApp(ui, server)
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.
As stated in the title, I'm trying to use Shiny in R to create a program that reads a csv file uploaded by the user, after which the user can select a variable from that file to view a plot that is plotted by ggplot. I'm trying to achieve this over two tabs, the first tab will read the file and the second tab will get the user to select the variable to view the plot.
My codes are as below. Currently, I am able to successfully read the user's file but I am not able to plot based on the variable selected (I currently only have 1 variable "Location" for demo). (HomeWTaxAmt is the y variable to plot against).
library(shiny)
library(ggplot2)
library(data.table)
library(RColorBrewer)
options(scipen=1000)
ui <- fluidPage(
navbarPage("User Interface:",tabPanel("Upload",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE),
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
tags$hr(),
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head"),
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"')),
mainPanel(
verbatimTextOutput("summary"),
tableOutput("contents")
))),
tabPanel("Graphing",
titlePanel("Plotting Graphs"),
sidebarLayout(
sidebarPanel(
selectInput("variable", "Variable:",
list("Location"))),
mainPanel(
h3(textOutput("caption")),
plotOutput("ggplot")
)
))
))
server <- function(input, output) {
output$contents <- renderTable({
req(input$file1)
library(data.table)
data <- fread(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
if(input$disp == "head") {
return(head(data))
}
else {
return(data)
}
})
output$summary <- renderPrint({
summary(data)
})
formulaText <- reactive(function() {
paste("HomeWTaxAmt ~", input$variable)
})
output$caption <- renderText(function() {
formulaText()
})
output$ggplot <- renderPlot(function() {
data <- fread(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
if(is.null(data)) return(NULL)
# check for the input variable
ggplot(data, aes(x=reorder(factor(data[input$variable]), -abs(HomeWTaxAmt), function(x){sum(x)}),
weight = abs(HomeWTaxAmt), fill = factor(data[input$variable]))) + geom_bar(show.legend=FALSE) + xlab(input$variable) +
scale_fill_manual(values=brewer.pal(n = 12, name = "Paired"))
})
}
shinyApp(ui, server)
As I did not have access to your exact .csv files I had to make some adjustments to the plotting command, but I'm pretty sure you can go from there and get it to work with your data. Please note that not loading a .csv file now gives you errors on the first tab, which dissapear as soon as data is loaded. You might want to use some ifelse switches here to ensure the end-user doesn't have to see these R-errors.
Here's the code that plots a plot as intended based on some sample data I had:
library(shiny)
library(ggplot2)
library(data.table)
library(RColorBrewer)
options(scipen=1000)
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# I didn't change anything in this section
ui <- fluidPage(
navbarPage("User Interface:",tabPanel("Upload",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE),
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
tags$hr(),
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head"),
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"')),
mainPanel(
verbatimTextOutput("summary"),
tableOutput("contents")
))),
tabPanel("Graphing",
titlePanel("Plotting Graphs"),
sidebarLayout(
sidebarPanel(
selectInput("variable", "Variable:",
list("Location"))),
mainPanel(
h3(textOutput("caption")),
plotOutput("ggplot")
)
))
))
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
server <- function(input, output, session) { # make sure to include "session" here, in order to update your inputs later
# create an reactive upload to access your data more quickly and easily
reactive_data <- reactive({
print(input$file1$datapath)
data <- fread(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
return(data)
})
# preview
# no library(data.table) required here, as its already loaded at the beginning of the script)
output$contents <- renderTable({
# load your data
data <- reactive_data()
if(input$disp == "head") {
return(head(data))
}
else {
return(data)
}
})
output$summary <- renderPrint({
summary(reactive_data())
})
formulaText <- reactive({ # no need for function() here
paste("HomeWTaxAmt ~", input$variable)
})
output$caption <- renderText({
formulaText()
})
output$ggplot <- renderPlot({
# load your data
data <- reactive_data()
# to only plot when data is not NULL, make sure to include the plotting command in the if-else statement
# no data
if(is.null(data)){
return(NULL)
}else{
# data
# update your selectInput first, so that all the variables match your .csv headers
updateSelectInput(session, "variable",
choices = colnames(data),
selected = input$variable) # this keeps the input on the last thing selected on tab-change
# check for the input variable
# I used aes_string here so that indexing the colnames works
# you'll have to adjust the plotting command to your needs as my .csv files aren't the same as yours
plot <- ggplot(data, aes_string(x=colnames(data)[colnames(data) == input$variable], colnames(data)[length(colnames(data))]))+
geom_bar(stat="identity")
# Display your plot
print(plot)
}
})
}
shinyApp(ui, server)
Modified your code a bit and i hope it helps you.
library(shiny)
library(ggplot2)
ui <- fluidPage(
navbarPage("User Interface:",tabPanel("Upload",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE),
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
tags$hr(),
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head"),
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"')),
mainPanel(
verbatimTextOutput("summary"),
tableOutput("contents")
))),
tabPanel("Graphing",
titlePanel("Plotting Graphs"),
sidebarLayout(
sidebarPanel( uiOutput("variable_x"),
uiOutput("variable_y")),
mainPanel(
h3(textOutput("caption")),
plotOutput("plot")
)
))
))
server <- function(input, output, session) {
onSessionEnded(stopApp)
data <- reactive({
req(input$file1)
df <- read.csv(input$file1$datapath, header = input$header, sep = input$sep, quote = input$quote)
return(df)
})
output$contents <- renderTable({
if (input$disp == "head") {
return(head(data()))
}
else {
return(data())
}
})
output$summary <- renderPrint({
summary(data())
})
output$variable_x <- renderUI({
selectInput("variableNames_x", label = "Variable_X", choices = names(data()))
})
output$variable_y <- renderUI({
selectInput("variableNames_y", label = "Variable_Y", choices = names(data()) )
})
dat <- reactive({
test <- data.frame(data()[[input$variableNames_x]], data()[[input$variableNames_y]])
colnames(test) <- c("X", "Y")
return(test)
})
output$plot <- renderPlot({
if (is.null(data)) { return(NULL)
} else {
ggplot(dat(),aes(x = X,y = Y)) + geom_point(colour = 'red',height = 400,width = 600) +
labs(y = input$variableNames_y,
x = input$variableNames_x,
title = "ggplot")
}
})
}
shinyApp(ui, server)
Note : I have changed your ggplot function but you can change as per your requirement.
I am new to shiny and I am trying to build an app but I have been stuck on this one issue for a while. The purpose of the app is so users can upload their data, select their independent and dependent variables, select their number of trees...etc and eventually have that run through a random forest script and display the outputs.
However, right now I am stuck on setting up the drop-down input where users can select their variables (headers from the data they uploaded). It needs to be reactive so they first upload their data and then the app automatically knows what to put in the drop-down menu because it would be NULL otherwise. Here are copies of my ui.R and server.R files. If you know what may be wrong, your help would greatly be appreciated. Also, thank you to the people who helped me last week. I did not upload the actual R code (just images) so it was extra challenging for them.
ui.R
library(shiny)
shinyUI(fluidPage(
headerPanel(title = "Upload File"),
sidebarLayout(
sidebarPanel(
fileInput("file","Upload the file"),
h5("Max file size is 5 MB"),
tags$hr(),
radioButtons("sep","Seperator", choices = c(Comma = ",", Period = ".", Tilde = "~",minus = "-")),
tags$hr(),
checkboxInput("header","Header", TRUE),
tags$hr(),
uiOutput("vx"),
tags$hr(),
uiOutput("vy"),
tags$hr(),
numericInput("MTRY", "Set the MTRY", 0, min = 0, max = 500, step = 1,
width = 100),
helpText("The MTRY should default to 0"),
numericInput("numtree", "Number of Trees", 500, min = 30, max = 10000, step = 100,
width = 100)
),
mainPanel(
tableOutput("input_file")
)
)
)
)
Server.R
library(shiny)
shinyServer(function(input, output) {
output$input_file <- renderTable({
file_to_read = input$file
if(is.null(file_to_read)){
return()
}
dat1 <- read.table(file_to_read$datapath, sep = input$sep, header = input$header)
return(dat1)
})
reactive1 = reactive({
if(is.null(dat1))
return()
D <- colnames(dat1)
reactive1[[1]] = D
reactive1[[2]] = D[1]
reactive1
})
output$vx <- renderUI({
selectInput("cols", "Select Dependent Variable",
choices = colnames(reactive1()[[1]]), selected = reactive1()[[2]][1])
})
output$vy <- renderUI({
selectInput("cols", "Select Independent Variables",
choices = colnames(reactive1()[[1]]), selected = reactive1()[[2]][1], multiple = T)
})
})
Here is what the app looks like after uploading a csv:
App
The key is to make the input data reactive and updateSelectInput based off of the reactive data frame. See below:
ui <- fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE),
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
tags$hr(),
selectInput("vars", "Label",choices = c("NULL"))
),
mainPanel(
tableOutput("contents")
)
)
)
server <- function(input, output, session) {
df1 <- reactive({
req(input$file1)
read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
})
observeEvent(df1(), {
updateSelectInput(session, "vars", choices = names(df1()))
})
}
shinyApp(ui, server)
Please comment if this answers your question.
I am trying to make a simple shiny app that takes information from a csv file and produces a table and two graphs. The content appears to be loading correctly but I can not seem to get the output to go within the specified tab, making the output appear cluttered and difficult to read. Any help is appreciated. Thank you in advance
library(ggplot2)
library(plater)
server <- function(input, output) {
output$table1 <- renderTable({
req(input$file1)
df <- read_plate(input$file1$datapath)
if(input$disp == "head") {
return(head(df))
}
else {
return(df)
}
data <- reactive({
read_plate(input$file1$datapath)
})
})
{output$Plot1 <- renderPlot({
req(input$file1)
df <- read_plate(input$file1$datapath)
ggplot(df, aes(x=Column, y=Row, size = 20, color = "variabley")) + geom_point()
})
}
output$vx <- renderUI({
req(input$file1)
df <- read_plate(input$file1$datapath)
selectInput("variablex", "Select the (X) Variable", choices = names(df))
})
output$vy <- renderUI({
req(input$file1)
df <- read_plate(input$file1$datapath)
selectInput("variabley", "Select the (y) Variable", choices = names(df))
})
output$p <- renderPlot({
req(input$file1)
df <- read_plate(input$file1$datapath)
ggplot(df, aes(input$variablex, input$variabley, size = 20)) + geom_point()
})
}
ui <- fluidPage(
titlePanel("Enrichment Analysis"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
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 = '"'),
#Checkbox
# Horizontal line ----
tags$hr(),
# Input: Select number of rows to display ----
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head")
),
mainPanel(
tabsetPanel(type = "tab",
tabPanel("Plot", fluid = TRUE,
sidebarLayout(
sidebarPanel(selectInput("colm", "Variable", choices = names(df), selected = "")),
mainPanel(
plotOutput("Plot1")
)
)
),
tabPanel("Plate"),
sidebarPanel(
uiOutput("vx"),
uiOutput("vy"),
mainPanel(plotOutput("p", width = "70%"))
),
tabPanel("Comparison"),
tabPanel("Table")),
tableOutput("table1")
)
)
)
shinyApp(ui, server )