This is my first question, so please be patient with me. I am trying to pass a dataset into an interactive shiny plot. Here is the gist of what I have on the server side.
# Load all necessary packages
load <- c(
"shiny",
"shinythemes",
"ggplot2",
"BH",
"DT",
"rCharts",
"markdown",
"data.table",
"dplyr"
)
loaded <- lapply(load, function(x) {
if (!require(x, character.only = T)) {
install.packages(x)
require(x, character.only = T)
}
})
# Define UI for application that draws a histogram
ui <- navbarPage(
"Testkit",
# Tabpanel for Upload and Overview ----
tabPanel(
"Upload & Overview",
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput(
"file1",
"Choose CSV File",
multiple = TRUE,
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"
),
# Horizontal line ----
tags$hr(),
# Input: First Variable ----
selectizeInput(
'e1',
'1. Select First Variables',
choices = NULL,
multiple = FALSE
),
# Horizontal line ----
tags$hr(),
# Input: Second Variable ----
selectizeInput(
'e2',
'2. Select Seconed Variables',
choices = NULL,
multiple = FALSE
)
),
# end of sidebarPanel
# Main panel for displaying outputs ----
mainPanel(
# Tabset panels for displaying outputs
tabsetPanel(
tabPanel(p(icon("area-chart"), "Single Graph"),
fluidPage(fluidRow(
column(
width = 12,
plotOutput(
"sPlot",
height = 700,
click = "sPlot_click",
brush = brushOpts(id = "sPlot_brush")
),
actionButton("exclude_toggle", "Toggle points"),
actionButton("exclude_reset", "Reset")
)
)))
# end of Single Graph tab) # end of tabPanel ) # end of mainPanel)))
# Define server logic required to draw a histogram
server <-
function(input, output, session) {
# Function for file upload ----
my_data <- reactive({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$file1)
df <- read.csv(
input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote
)
if (input$disp == "head") {
return(head(df))
}
else {
return(df)
}
})
# Pass list of variables to selectize ----
observe(updateSelectizeInput(session, 'e1', choices = colnames(select(
my_data(), contains("Var_")
))))
observe(updateSelectizeInput(session, 'e2', choices = colnames(select(
my_data(), contains("Var_")
))))
# Function for sectioning table ----
sliceData <- reactive({
sData <- my_data() %>%
select(one_of(c(input$e1, input$e2)))
return(sData)
})
# Create output for interactive plot tab ----
vals <-
reactiveValues(keeprows = rep(TRUE, nrow(sliceData())))
IA_Plot <- reactive({
# Plot the kept and excluded points as two separate data sets
keep <-
sliceData()[vals$keeprows, , drop = FALSE]
exclude <-
sliceData()[!vals$keeprows, , drop = FALSE]
IAP <-
ggplot(keep, aes(input$e1, input$e1)) + geom_point() +
geom_smooth(method = lm,
fullrange = TRUE,
color = "black") +
geom_point(
data = exclude,
shape = 21,
fill = NA,
color = "black",
alpha = 0.25
) +
coord_cartesian(xlim = c(1.5, 5.5), ylim = c(5, 35))
IAP
})
# Create single graph plot for interaction ----
output$sPlot <- renderPlot({
IA_Plot()
})
# Toggle points that are clicked ----
observeEvent(input$sPlot_click, {
res <- nearPoints(sliceData(), input$sPlot_click, allRows = TRUE)
vals$keeprows <-
xor(vals$keeprows, res$selected_)
})
# Toggle points that are brushed, when button is clicked ----
observeEvent(input$exclude_toggle, {
res <- brushedPoints(sliceData(), input$sPlot_brush, allRows = TRUE)
vals$keeprows <-
xor(vals$keeprows, res$selected_)
})
# Reset all points ----
observeEvent(input$exclude_reset, {
vals$keeprows <- rep(TRUE, nrow(sliceData()))
})
}
# Run the application
shinyApp(ui = ui, server = server
)
Here is the error I got from R Studio:
Warning: Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
Could someone help me with what I am missing?
Thanks!!
The error you are getting is from vals <- reactiveValues(keeprows = rep(TRUE, nrow(sliceData()))). You can read the reactive expressions only inside observe
Try putting that statement inside observe, something like this:
observe({
vals <-reactiveValues(keeprows = rep(TRUE, nrow(sliceData())))
})
Hope it helps!
Related
I want to update one of my selectInputs, "variable" with a reactive list of countries that will change depending on the dataset that is selected in another selectInput, "Databases". I want the default list of choices to be the "Home File" dataset that is loaded when the app runs but I want to have the option of switching to an uploaded file. The files I plan to upload will all have the list of countries under the "Countries" column to match the home_df column. Ideally the list will refresh anytime the dataset is switched.
So far I have tried this but cant seem to return the values I want:
Values <- c(145540,145560, 157247, 145566)
Countries <- c(US, Canada, Ireland, Spain)
Zipcodes <- c(145592, 145560, 145566, NA)
home_df <- data.frame(Values , Countries , Zipcodes )
ui <- fluidPage(
tabPanel(
"first_plot",
tabsetPanel(
id = "firstPanel",
type = "tabs",
tabPanel("File Upload",
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
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"
)
),
mainPanel(# Output: Data file ----
tableOutput("contents"))
)),
tabPanel("first_plot",
uiOutput("box"))
server <- function(input, output, session) {
my_data <- reactive({
inFile <- input$file1
req(inFile)
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch({
df_x <<- read.csv(
inFile$datapath,
header = input$header,
sep = input$sep,
quote = input$quote
)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
})
if (input$disp == "head") {
return(head(df_x))
}
else {
return(df_x)
}
})
}
datasetInput <- reactiveValues(
if (input$exp_pr_box == "Home File"){
dataset <- home_df
}
else if (input$exp_pr_box == "Uploaded DB"){
dataset <- my_data()
}
return(dataset)
)
md <- reactiveValues(
list = datasetInput$Countries
)
observeEvent(datasetInput(),
updateSelectInput(session, "variable", choices=md()))
output$box <- renderUI({
tabPanel(
"first_plot",
sidebarPanel(
selectInput(
"exp_pr_box",
"Database",
choices = c("Home File", "Uploaded DB")
), ----
selectInput("variable", "Selection:", choices=NULL, selected = NULL
)
)
),
mainPanel(
h3("plot title", align = "center"),
plotlyOutput("plot", height = '1000px', width = "100%")
)
)
})
output$contents <- renderTable({
my_data()
})
output$plot <- renderPlotly(
ggplot(dx) +
geom_boxplot(col = c("#69b3a2", "red")) +
geom_line(data = dx, aes(group = paired), color =
"grey"))
shinyApp(ui, server)
I was able to solve the issue with the help of this post (R Shiny - How to update a dependent reactive selectInput before updating dependent reactive plot)
And by storing the list in the reactive. For some reason using the names function as was done in the example did not output the list for me but worked after removing it
md <- reactive({
my_list = input_dataset()
})
observeEvent(input$exp_pr_box, {
freezeReactiveValue(input, "variable")
updateSelectInput(session = session, inputId = "variable", choices = unique(str_to_title(md())))
})
library(shiny)
library(plotly)
library(ggplot2)
library(tidyverse)
library(DT)
if (!require("okcupiddata")) install.packages("okcupiddata")
library(okcupiddata)
D=sample_n(profiles, 5000)
write.csv(D, file="~/Downloads/OKCupid.csv", row.names = FALSE)
ui <- fluidPage(
# Application title
titlePanel(title = "Uploading Your File"),
sidebarLayout(
sidebarPanel(
width = 2,
## Create a file upload control
fileInput(inputId = "file",
label = "Choose Your File:",
accept = c(".txt", ".csv")),
## Use html tag hr (horizontal rule) to make a horizontal separator
hr(),
## Make a h5 heading
h5("Max file size is 2M"),
## Create a checkbox that can be used to specify logical values.
checkboxInput(inputId = "header",
label = "Header",
value = TRUE),
## Create a set of radio buttons used to select an item from a list.
radioButtons(inputId = "sep",
label = "Separator",
choices = c(Comma = ",", Space = " ", Tab = "\t")),
uiOutput("variable")
),
mainPanel(
tabsetPanel(
tabPanel("Table", tableOutput("table")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Plot", plotlyOutput("plot", height = "700px"))
)
)
)
)
server <- function(input, output, session) {
myData <- reactive({
f = input$file
if (is.null(f)){
return(NULL)
} else {
read.table(f$datapath, header = input$header, sep = input$sep)
}
})
#A. Create a drop-down menu to choose a variable
output$variable <- renderUI({
})
#B. Display the whole table
output$table <- renderTable({
})
#C. Summarize the whole table
output$summary <- renderPrint({
})
#D. Plot only the selected variable.
# The code needs to handle both a categorical and numeric variables
output$plot <- renderPlotly({
})
}
shinyApp(ui = ui, server = server)
I'm stuck on A, B, C, and D. I know to use selectInput() to create a drop down menu, a data frame() function to render a table, a summary() function to render a summary, and a ggplot() function to render both a numeric and categorical plot.I don't know how to correctly reference the selected file and then reference the column from said file. Any ideas?
The answer completes A, B, C and D. You haven't really shared what kind of plot you need but based on class of the column selected this displays the plot.
library(shiny)
library(plotly)
library(tidyverse)
library(DT)
ui <- fluidPage(
# Application title
titlePanel(title = "Uploading Your File"),
sidebarLayout(
sidebarPanel(
width = 2,
## Create a file upload control
fileInput(inputId = "file",
label = "Choose Your File:",
accept = c(".txt", ".csv")),
## Use html tag hr (horizontal rule) to make a horizontal separator
hr(),
## Make a h5 heading
h5("Max file size is 2M"),
## Create a checkbox that can be used to specify logical values.
checkboxInput(inputId = "header",
label = "Header",
value = TRUE),
## Create a set of radio buttons used to select an item from a list.
radioButtons(inputId = "sep",
label = "Separator",
choices = c(Comma = ",", Space = " ", Tab = "\t")),
uiOutput("variable")
),
mainPanel(
tabsetPanel(
tabPanel("Table", tableOutput("table")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Plot", plotlyOutput("plot", height = "700px"))
)
)
)
)
server <- function(input, output, session) {
myData <- reactive({
f = input$file
if (is.null(f)){
return(NULL)
} else {
read.table(f$datapath, header = input$header, sep = input$sep)
}
})
#A. Create a drop-down menu to choose a variable
output$variable <- renderUI({
selectInput('dd', 'Select dropdown', names(myData()))
})
#B. Display the whole table
output$table <- renderTable({
myData()
})
#C. Summarize the whole table
output$summary <- renderPrint({
summary(myData())
})
#D. Plot only the selected variable.
# The code needs to handle both a categorical and numeric variables
output$plot <- renderPlotly({
if(is.numeric(myData()[[input$dd]]))
plt <- ggplot(myData(), aes(.data[[input$dd]])) + geom_histogram()
else
plt <- ggplot(myData(), aes(.data[[input$dd]])) + geom_bar()
ggplotly(plt)
})
}
shinyApp(ui = ui, server = server)
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 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 )
I am trying to create a simple shiny app that can load data from a csv file and display a ggplot with a best fit line.
I have a file uploader widget and when I upload a file, such as a csv, a red warning message briefly pops up saying (I think... it disappears so quickly I'm not 100% sure I read it correctly) "undefined column selected in dataframe".
It then disappears and a plot appears. So my app is working almost exactly how I'd like it to work, I would just like to avoid the brief warning from appearing.
I know it is due to my renderPlot function (at the bottom of my server.R file). I'm just not sure what to change to prevent the error from occurring. I commented out a bunch of failed attempts to make this problem go away.
The shiny app is hosted here and this is the csv file I've been using to test it.
My server.R code:
library(shiny)
library(ggplot2)
# Define server logic required to draw a histogram
shinyServer(function(input, output,session) {
data <- reactive({
req(input$file)
df <- read.csv(input$file$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
if(input$disp == "head") {
return(head(df))
}
else {
return(df)
}
})
output$contents <- renderTable({
req(data())
data()
})
#UPDATE SELECT OPTIONS TO MATCH DATAFRAME COLUMN NAMES
observeEvent(input$file, {
vars <- colnames(data())
updateSelectInput(session, "x",
label = "Horizontal Axis Variable Column",
choices = vars, selected = vars[1])
updateSelectizeInput(session, "xname",
label = 'Horizontal Axis Variable Name',
choices = vars,selected = vars[1],
options = list(create = TRUE),server = TRUE)
updateSelectInput(session, "y",
label = "Vertical Axis Variable Column",
choices = vars, selected = vars[2])
updateSelectizeInput(session, "yname",
label = 'Vertical Axis Variable Name',
choices = vars,selected = vars[2],
options = list(create = TRUE),server = TRUE)
})
#Update x variable name to match selected x variable.
observeEvent(input$x, {
updateSelectizeInput(session,"xname",
label = 'Horizontal Axis Variable Name',
choices = input$x, selected = input$x)
})
#update y variable name to match selected y variable
observeEvent(input$y, {
updateSelectizeInput(session,"yname",
label = 'Vertical Axis Variable Name',
choices = input$y, selected = input$y)
})
#update x and y variables... had same problem when I used
# input$x and input$y inside of renderPlot
x <- reactive({input$x})
y <- reactive({
input$y
})
#names for axes and title labels
xname <- reactive({input$xname})
yname <- reactive({input$yname})
title <- reactive({input$title})
output$plot <- renderPlot({
if (is.null(x()) | is.null(y())) {
return()
}
# req(data())
# req(ncol(data() >= 2))
# req(x())
# req(y())
ggplot(data = data(), aes(x = data()[,x()], y = data()[,y()])) +
geom_point() +
xlab(xname()) +
ylab(yname()) +
ggtitle(title()) +
if(input$options == "Display Best Fit Line"){
geom_smooth(method = 'lm', se = FALSE, formula = y ~ x)
}
})
})
my ui.R script:
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Shiny Graphing App"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
# Input: Select a file ----
fileInput("file", "Choose CSV File",
multiple = TRUE,
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"),
textInput(inputId = "title", label = "Plot Title", value = ""),
selectInput(inputId = "x",
label = "Horizontal Axis Variable Column", choices = c()),
selectInput(inputId = "y",
label = "Vertical Axis Variable Column",
choices = c()),
selectizeInput(inputId = 'xname',
label = 'Horizontal Axis Variable Name',
choices = c(),
options = list(create = TRUE)),
selectizeInput(inputId = 'yname',
label = 'Vertical Axis Variable Name',
choices = c(),
options = list(create = TRUE)),
radioButtons(inputId = 'options',
label = 'Options',
choices = c("Display Best Fit Line","Display Points Only"))
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("plot"),
tableOutput("contents")
)
)
))
Thanks in advance for trying to help.