Passing column name via selectInput in shiny application - r

I have a simple shiny app, I would like to pass the value from the selectInput as a column name of data frame and use it in ggplot. My UI code looks like that:
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("Title"),
# Sidebar with a slider input for the number of bins
sidebarLayout(
sidebarPanel(
selectInput(inputId = "yaxis",
label = "Y-axis",
choices = list("Overall Rank" = "overall_rank",
"Income Deprivation" = "income_deprivation_rank"),
selected = "income_deprivation_rank"),
selectInput(inputId = "xaxis",
label = "X-axis",
choices = list("Overall Rank" = "overall_rank",
"Income Deprivation" = "income_deprivation_rank"),
selected = "overall_rank")),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
h5("Notes"),
p("notes")
)
)
))
My server side code is vary simple, I have a SPARQL query (cut here to save the space) that creates simple data frame:
# Libs
require(shiny); require(SPARQL); require(ggplot2)
# Server function
shinyServer(function(input, output) {
# Source the data
## Define endpoint URL.
endpoint <- "http://data.opendatascotland.org/sparql.csv"
### Create Query
query.simd <- "PREFIX stats: <http://statistics.data.gov.uk/id/statistical-geography/>
(...) cut to save space (...)"
## Make the data
dta.simd<- SPARQL(url = endpoint, query = query.simd, format = "csv")$results
## Make the plot
output$distPlot <- renderPlot({
xaxis <- as.character(input$xaxis)
yaxis <- as.character(input$yaxis)
# draw the the plot
ggplot(data = dta.simd, aes(x = xaxis, y = yaxis)) +
geom_point(shape=1)
})
})
The query results in a simple data frame, resambling the extract below:
observation overall_rank income_deprivation_rank
a001 2 6
a002 10 7
a003 11 9
After compiling the app I keep on receiving the Error: object 'xaxis' not found. This leads me to believe that for whatever reason the value from the input$xaxis is not passes to the xaxis object and cannot be used in ggplot. If I decide to replace the as.character(input$yaxis) with a string corresponding to the column name, like for instance overall_rank and the other one income_deprivation_rank the app works as it should, so the problem is clearly associated with using the input$xaxis value. I tried the code with no as.character() function but got the same error message.

Wherever you would normally reference the column name as a string like input$colName, replace it with get(input$colName). This way Shiny knows to fetch the value of input$colName instead of treating it as a string.

Related

Scatterplot and Shiny

I am still quite new to shiny and ggplot so I am not sure what is causing the problem and I have posted different problems with this code previously however I have come across a new issue... when I run the code my plot does not appear and instead I get an error: Warning: Error in FUN: object "total_pigs" not found.
I get this error regardless of the options I choose in the selectInput "x"function.
I have a separate CSV file within the same directory as the app.R file. The selectInput(s) matches the columns and rows within the CSV, I was hoping that my code would simply read the data stored within it and this will generate my plot points.
library(shiny)
library(ggplot2)
path <- file.path("eu_pigs.csv", stringsAsFactors = FALSE)
ui <- fluidPage(
titlePanel("Breeding Numbers 2016 - 2018 (pig)"),
sidebarLayout(
sidebarPanel(
selectInput(inputId = "x",
label = "Pig Breeds:",
choices = c("total_pigs", "female_breeding_herd",
"in_pig_sows", "in_pig_gifts", "other_sows",
"maiden_gilts", "boars_for_service", "other_pigs"),
selected = "total_pigs"),
selectInput(inputId = "y",
label = "Year by year change:",
choices = c(2016, 2017, 2018, sep = ""),
selected = 2016)
),
mainPanel(
plotOutput(outputId = "scatterplot")
)
)
)
server <- (function(input, output) {
output$scatterplot <- renderPlot({
ggplot(data = read.csv("eu_pigs.csv")) +
aes_string(x = input$x, y = input$y) +
geom_point()
})
})
shinyApp(ui, server)
I attach an image of my csv file.
As DS_UNI suggests, the issue probably lies with the structure of your data. ggplot2 wants to work with tidy data, so in this case that would mean each row represents a case, i.e. a year.
Here's what I think you need to do, although this is making some assumptions about what you want the end result to look like!
Step one: Read in the csv for data wrangling
pigs_data <- read.csv("eu_pigs.csv")
Step two: Make the first column into row names
row.names(pigs_data) <- pigs_data$pig_breeds
pigs_data[1] <- NULL
Step three: Transpose the data
pigs_data <- t(pigs_data)
You would then use pigs_data in your ggplot data argument.

Plotly working when using ggplot() but not when using plot_ly() on shiny server

I am having an issue with using Plotly on my shiny server. I have a clustering app where I bring in a data file and you are able to perform two variable and three variable clustering. The first tab is the two variable clustering. I use ggplot() to create the plot and then using Plotly's ggplotly() function to make it a plotly object to enable interactivity. This renders fine on the app's page.
The issue here is when plotting the three variable clustering. Instead of ggplot() and then ggploty(), I use Plotly's function plot_ly(). This allows me to pass an x, y, and z variable. It works like a charm on my local machine, but when on the shiny server I get this error Error: An error has occurred. Check your logs or contact the app author for clarification. I open my logs and do a hard refresh of the app, no logs are showing. My package versions are the same for both my shiny server and my local machine. The error is not every telling here and I have tried to google around but I am getting no where.
Here is the code:
server.R
## Needed Lib's
library(shiny)
library(ggplot2)
library(plotly)
library(DT)
library(cluster)
## Initiate the severer
shinyServer(
function(input, output, session) {
## Display the text that describes why to use this app/method for grouping
output$text <- renderText({
## Let the user know which tab they have selected
{paste0("You are viewing the \"", input$ClusterChoice, "\"")}
})
## Display the text that describes why to use this app/method for grouping
output$why_text <- renderText({
## Let the user know which tab they have selected
"This is why"
})
# Variable #1
output$varselect1 <- renderUI({
selectInput("var1", label = "Select first variable for clustering:",
choices = names(dataset()), selected = names(dataset())[1])
})
# Variable #2
output$varselect2 <- renderUI({
selectInput("var2", label = "Select second variable for clustering:",
choices = names(dataset()), selected = names(dataset())[2])
})
## Clustering with third variable
# Variable #1
output$varselect3 <- renderUI({
selectInput("var3", label = "Select third variable for clustering (only works in Multiple Variable Tiering Tab):",
choices = names(dataset()), selected = names(dataset())[3])
})
## Read in the data
dataset <- reactive({
infile <- input$datafile
if (is.null(infile)) {
return(NULL)
}
else {read.csv(infile$datapath)}
})
## Compute the K means algo
compute_kmeans <- reactive({
# Choose between simple K means or a more complex K means with third variable
if (input$ClusterChoice == 'Two Variable Tiering') {
data <- subset(dataset(), select = c(input$var1, input$var2))
# Scale the data. Using "standardized" here. This will center and then scale the data
#data <- scale(data, center = TRUE)
# Change some columns names
colnames(data) <- c('x', 'y')
data <- na.omit(data)
# Set the seed
set.seed(111)
# Cluster
Kclust <- kmeans(data, input$k)
# Save results to a list
kmean.result <- list(kmean.result = data.frame(data, cluster = as.factor(Kclust$cluster)))
return(kmean.result)
}
# K means with third variable
else { (input$ClusterChoice == 'Multiple Variable Tiering')
three_var_data <- subset(dataset(), select = c(input$var1, input$var2, input$var3))
# Scale the data. Using "standardized" here. This will center and then scale the data
#three_var_data <- scale(three_var_data, center = TRUE)
three_var_data <- na.omit(three_var_data)
# Set the seed
set.seed(111)
# Cluster
Kclust <- kmeans(three_var_data, input$k)
kmean.result <- list(kmean.result = data.frame(three_var_data, cluster = as.factor(Kclust$cluster)))
return(kmean.result)
}
})
## Create a dataframe of the K means & K means with third variable results
kmeans_results <- reactive({
# For only two variables
if (input$ClusterChoice == 'Two Variable Tiering') {
# Call the method that computes the k means
data <- compute_kmeans()
# Save the results into a df
results <- data$kmean.result
results_df <- data.frame(results)
colnames(results_df) <- c(input$var1, input$var2, 'Grouping')
return(results_df)
}
# For more than two variables
else { (input$ClusterChoice == 'Multiple Variable Tiering')
# Call the method that computes the k means with third variable
three_var_data <- compute_kmeans()
# Save the results into a df
three_var_results <- three_var_data$kmean.result
three_var_results_df <- data.frame(three_var_results)
colnames(three_var_results_df) <- c(input$var1,
input$var2,
input$var3,
'Grouping')
return(three_var_results_df)
}
})
## Results of each K means & K means with third variable
master_results <- reactive({
# Call the method that stores the raw input data
data <- dataset()
# For only two variables
if(input$ClusterChoice == 'Two Variable Tiering') {
# Call the method that stores the K means results
kmean_results <- kmeans_results()
# Merge the K means results with the raw input data
results <- merge(kmean_results, data)
results <- results[!duplicated(results), ]
return(results)
}
# For more than two variables
else { (input$ClusterChoice == 'Multiple Variable Tiering')
# Call the method that stores the K means with third variable results
kmean_three_var_results <- kmeans_results()
# Merge the K means with third variable results with the raw input data
three_var_resutls <- merge(kmean_three_var_results, data)
three_var_resutls <- three_var_resutls[!duplicated(three_var_resutls), ]
return(three_var_resutls)
}
})
## Plot the K means results
output$plot <- renderPlotly({
graphics.off()
pdf(NULL)
# For only two variables
if (input$ClusterChoice == 'Two Variable Tiering') {
# Call the K means results method
results <- master_results()
# Change the x & y variables so we can call it in the tool-tip
x_axis <- results[[input$var1]]
y_axis <- results[[input$var2]]
# Plot
plot <- ggplot(data = results,
aes(x = x_axis,
y = y_axis,
color = Grouping,
name = Markets)) +
geom_point(size = 2) +
ggtitle("Grouping Results") +
labs(x = input$var1, y = input$var2)
# Use Plotly for interactivity
plotly_plot <- ggplotly(plot)
return(plotly_plot)
}
# For more than two variables
else if (input$ClusterChoice == 'Multiple Variable Tiering')
# Call the K means and third variable
three_var_resutls <- master_results()
# Change x, y, & z variables so we can call it in the tool-tip
x_axis <- three_var_resutls[[input$var1]]
y_axis <- three_var_resutls[[input$var2]]
z_axis <- three_var_resutls[[input$var3]]
# Plot (using Plotly for interactivity)
three_var_plot <- plot_ly(three_var_resutls,
x = x_axis,
y = y_axis,
z = z_axis,
color = factor(three_var_resutls$Grouping),
text = ~paste('Markets:', three_var_resutls$Markets,
'<br>Grouping:', three_var_resutls$Grouping)) %>%
add_markers() %>%
layout(title = 'Grouping Results',
scene = list(xaxis = list(title = input$var1),
yaxis = list(title = input$var2),
zaxis = list(title = input$var3)))
return(three_var_plot)
})
## Render the K means and K means with third variable results to a data table
output$cluster_table <- DT::renderDataTable({
# For only two variables
if (input$ClusterChoice == 'Two Variable Tiering') {
# Call results method
results <- master_results()
# Render data table
datatable(results,
# Get rid of row indexes
rownames = FALSE,
# Enable downloading options
extensions = 'Buttons',
options = list(
dom = "Blfrtip",
buttons =
list("copy", list(
extend = "collection",
buttons = c("csv", "excel", "pdf"),
text = "Download")),
lengthMenu = list(c(10, 20, -1),
c(10, 20, "All")),
pageLength = 10))
}
else if (input$ClusterChoice == 'Multiple Variable Tiering') {
# Call results method
results_three_var <- master_results()
# Render data table
datatable(results_three_var,
# Get rid of row indexes
rownames = FALSE,
# Enable downloading options
extensions = 'Buttons',
options = list(
dom = "Blfrtip",
buttons =
list("copy", list(
extend = "collection",
buttons = c("csv", "excel", "pdf"),
text = "Download")),
lengthMenu = list(c(10, 20, -1),
c(10, 20, "All")),
pageLength = 10))
}
})
}
)
ui.r
## Needed Lib's
library(shiny)
library(plotly)
## Start the UI renderer
shinyUI(
pageWithSidebar(
## The TITLE!
headerPanel("Grouping Data Together"),
## This is where the up-loader and drop downs live
sidebarPanel(
fileInput('datafile',
'Choose CSV file',
accept=c('text/csv', 'text/comma-separated-values,text/plain')),
uiOutput("varselect1"),
uiOutput("varselect2"),
uiOutput("varselect3"),
numericInput('k', 'Number of clusters', value = 3, min = 1, step = 1)),
## The main panel where all the shit happens
mainPanel(
textOutput("text"),
tabsetPanel(id = 'ClusterChoice',
tabPanel("Two Variable Tiering", value = 'Two Variable Tiering'),
tabPanel("Multiple Variable Tiering", value = 'Multiple Variable Tiering'),
tabPanel("Why Do It This Way?", value = "Why Do It This Way?")
),
## Description of this app
h2("Description"),
p("This tool's main functionality is to quickly put your data into groups. The file that is being uploaded
should only be the data that you want to group together. For example, if you have data that is broken out
by Markets (DMA) and you want to group those Markets into similar groupings you should upload all data
that you think is important to those groupings. Then via the drop downs you can select the 2 or 3 variables
you think best represents the groupings."),
## The tabs
h2("The Different Tabs"),
p("Tab #1: This tab is only when you want to use 2 variables in your data to create the groupings."),
p("Tab #2: This tab is only when you want to use 3 variables in your data to create the groupings."),
## Instructions for using this app
h2("Instructions"),
p("Please follow these instructions to create your groupings."),
p("1. Upload a data file (.csv) that will be used for making your groups.
The first row in the .csv file should be the column headers of the data.
The first column in the .csv file should be where your data starts.
THERE SHOULD BE NO 'BUFFERS' AROUND YOUR DATA FILE, i.e. empty rows and columns."),
p("2. Pick the variables you want to create the groupings off of via the drop-downs"),
p("3. Indicate the desired number of groups via the last drop-down."),
## The plot instructions
h2("Visualizing Your Grouped Data"),
p("You can download the plot as a .png file by hovering over the plot and selecting the
camera icon in the upper right hand side of the plot."),
# Plotly function that links the UI to the Server
plotlyOutput('plot', height = 700),
## The grouping data table instructions
h2("The Groupings"),
p("Instructions for downloading data:"),
p("1. To download the data use the drop-down below, labeled 'Show entries', to show 'All' entries."),
p("2. Click the 'Download' button and then select the type of file (PDF, excel, csv)."),
p("3. (Optional) You can copy the data that is shown to your clipboard is paste it into an excel/csv document."),
# JS DataTable function that links the UI to the Server
DT::dataTableOutput("cluster_table"))
)
)

How do I use the NULL Value as a variable call in R Shiny

How do I pass NULL as a Variable Value in RSHINY?
In phyloseq, there is a plot called plot_net.
The most basic plot_net plot code looks like this:
data(enterotype)
#Eliminate samples with no entereotype denomination
enterotype = subset_samples(enterotype, !is.na(Enterotype))
plot_net(enterotype, maxdist = 0.1, point_label = NULL)
I am trying to create an RShiny app which allows a user to alter this graphic.
point_label has several different options (ex: "SecTech", "SampleID", NULL).
I already have all of the other values for this label, I am just not sure how to add NULL.
Here is what I did:
This might not run since it isn't in a shiny app but I included it as an example to illustrate the issue.
library(shiny)
library(phyloseq)
# Data: This data contains info about nodes and edges on Phyloseq data.
data(enterotype)
#Eliminate samples with no entereotype denomination. Make it a lesson to
always catalogue data correctly from the start.
enterotype = subset_samples(enterotype, !is.na(Enterotype))
# a is the collection of variable names for point_label
a <- sample_variables(enterotype)
theme_set(theme_bw())
# Define UI for application that draws a network plot
shinyUI(fluidPage(
# Application title
titlePanel("Network Plots"),
sidebarLayout(
sidebarPanel(
selectInput("labelBy",
"Select the point label category",
***choices = c(a, "NA" = NULL),***
selected = "NA")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("netPlot")#,
#plotOutput("networkPlot")
)
)
))
shinyServer(function(input, output) {
output$netPlot <- renderPlot({
plot_net(enterotype, maxdist = .1, point_label = input$labelBy)
})
})
shinyApp(ui = ui, server = server)
This line is my question:
choices = c(a, "NA" = NULL)
How do I add NULL to my list of choices. No matter how I tried it, NULL was always taken as a zero value and it does not appear as an option.
If I write NULL as "NULL', the phyloseq function plot_net doesn't take it.
It only takes the value point_label = NULL for no value.
I think that it is possible to create an if... else loop where if a user clicks NULL on a checkboxInput then the plot will be generated by a second line of code specifying that the value in point_label is NULL, but that can be really cumbersome if there are several variables with a possible NULL Value.
There probably is some obvious trick like placing a $ or % in front of the NULL value but I couldn't find it. If anyone could help it would be great!
I don't think there is a way to use NULL in selectInput. Here's an alternative which you almost worked out - Use "None" (or any other replacement value) in selectInput and switch it with NULL while plotting. This way you don't have to write multiple if...else.
# update on UI side
selectInput("labelBy",
"Select the point label category",
choices = c("None", a),
selected = "None")
# update on server side
output$netPlot <- renderPlot({
point_labels <- switch(input$labelBy, "None" = NULL, input$labelBy)
plot_net(enterotype, maxdist = .1, point_label = point_labels)
})

Creating baseline comparison data in shiny R - Duplicating inputted dataframe

The aim of this exercise is to allow users to compare two different models based on their inputs. To do this, I have created an action button that asks users to specify their base model, and a reset button that takes the dataset back to before the baseline was added. The "base" logical determines whether the user wishes to include the base or not.
Once the add baseline actionbutton is clicked, the current state of the data.frame is saved and grouping variable is renamed with "baseline" added before it (using paste). Users can select a different model which renders in comparison to this static base.
For some reason, I cannot get the observe event to change the dataset. The observe event creates the baseline dataset fine (tested with print() ), however, the if() function does not alter "data" and therefore stops the base added to the ggplot. The code is written like this for two reasons. 1) by including the if() function after the observe event, any further changes to data only changes "data", it then gets added to the unchanged baseline data. 2) Also allows for the creation of the reset button which simply resets the data.frame to before the rbinding took place.
This small issue has infuriated me and I cannot see where I am going wrong. Cheers in advance for any help people can provide. There are simplier ways to do this (open to suggestions), however, the iris data is only an example of the function, and the actual version is more complex.
library("ggplot2")
if (interactive()) {
ui <- fluidPage(
selectInput("rows", label = h3("Choose your species"),
choices = list("setosa", "versicolor", "virginica")
),
actionButton("base", "Create baseline"),
actionButton("reset", "Reset baseline"),
plotOutput(outputId = "plot")
) # close fluid page
server <- function(input, output) {
output$plot <- renderPlot({ # create plot
base <- "no" # create baseline indicator which we can change once the observeevent below is changed
data <- iris
data <- iris[which(data$Species == input$rows),] # Get datasubset based on user input
observeEvent(input$base, { # If base is Pressed, run code below:
baseline <- data # Make Baseline Data by duplicating the users' specification
baseline$Species <- paste("Baseline",
data$Species, sep = "_") # Rename the grouping variable to add Baseline B4 it
base <- "yes" # Change our indicator of whether a baseline had been made to yes
}) # Close observe Event
observeEvent(input$reset, {
base <- "no" # This is placed before the rbind so that if we want to reset it will stop the merging of the two dataframes before it happens.
})
if (base == "yes") {
data <- rbind(data, baseline) # Run once the observe event has changed baseline to yes.This is kept seperatel that way any subsequent changes to data will not effect
# the final data. This command will simple add the base onto the changed "data" before plotting
}
observeEvent(input$reset, {
base <- "no"
})
ggplot(data, aes(x=Petal.Width, y = as.numeric(Sepal.Width), colour = Species)) + # variable = each dataset selected, value = respective values for that model
labs(x="Hypothetical X", y="Hypothetical X") +
geom_line()
}) # Close Render Plot
} # Close Serve Function
shinyApp(ui, server)
}
EXAMPLE TWO WITH REACTIVE OBJECT
library(shiny)
library(ggplot2)
library("tidyr")
library("dplyr")
library("data.table")
# Lets make a fake dataset called "Data". Has 4 variable options and
the Ages each data point relates to.
Ages <- 1:750
Variable1 <- rnorm(n=750, sd = 2, mean = 0)
Variable2 <- rnorm(n=750, sd = 1, mean = 2)
Variable3 <- rnorm(n=750, sd = 8, mean = 6)
Variable4 <- rnorm(n=750, sd = 3, mean = 3)
Data <- as.data.frame(cbind(Ages, Variable1, Variable2, Variable3,
Variable4) )
### UI
ui <- fluidPage(
checkboxGroupInput(inputId = "columns",
label = h4("Which Variables would you like in your
model?"), # Input Checkbox
choices = c("Variable1", "Variable2", "Variable3",
"Variable4")),
plotOutput(outputId = "plot"),
# Lets have our plot
actionButton("base", "Create baseline"),
# Baseline action
actionButton("reset", "Reset baseline") # Reset Action
) # Close UI
server <- function(input, output) {
output$plot <- renderPlot({
validate(need(!is.null(input$columns), 'Please tick a box to show a
plot.')) # Place a please choose columns for null input
data <- gather(select(Data, "Ages", input$columns), variable, value, -
Ages) ## Just doing a little data manipulation to change from wide to
long form. This allows for calculations down the track and easier
plotting
# Now we can modify the data in some way, for example adding 1. Will
eventually add lots of model modifications here.
data$value <- data$value + 1
rVals <- reactiveValues() # Now we create the reactive
values object
rVals[['data']] <- data # Making a reactive values
function. Place Data as "data".
observeEvent(input$base,{
baseline <- data
baseline$variable <- paste("Baseline",
baseline$variable, sep = "_")
# Rename Variables to Baseline preamble
rVals[['baseline']] <- baseline
# Put the new data into the reactive object under "baseline"
})
observeEvent(input$reset,{ # Reset button will wipe the
data
rVals[['baseline']] <- NULL
})
if(!is.null(rVals[['baseline']])) # if a baseline has been .
created, then
{rVals[['final']] <- bind_rows(rVals[['data']], rVals[['baseline']])
# Here we can simply bind the two datasets together if Baseline exists
} else {rVals[['final']] <- rVals[['data']]}
# Otherwise we can use keep it as it is
## Make our Plot !
ggplot(rVals[['final']], aes(x=Ages, y = as.numeric(value), colour =
variable)) + # variable = each dataset selected, value = respective
values for that model
labs(x="Age", y="value") +
geom_line()
}) ## Close the render plot
} ## Close the server
shinyApp(ui, server)
You have observer inside reactive expression, i have seen this causing problems on number of occasions when i was correcting shiny code. Create reactive expression (your plot function) and observers only to specify which is the baseline value of species (character string) then feed this to filtering data inside the plot function:
library(shiny)
library(ggplot2)
ui <- fluidPage(
selectInput("rows", label = h3("Choose your species"),
choices = list("setosa", "versicolor", "virginica")
),
actionButton("base", "Create baseline"),
actionButton("reset", "Reset baseline"),
plotOutput(outputId = "plot")
) # close fluid page
server <- function(input, output) {
rVals = reactiveValues()
rVals[['data']] = iris
rVals[['baseline']] = NULL
output$plot <- renderPlot({
# here we duplicate table to manipulate it before rendering
# the reason for duplicate is that you dont want to affect your
# base data as it may be used elsewhere
# note that due to R's copy-on-write this may be expensive operation and
# have impact on app performance
# in all cases using data.table package is recommended to mitigate
# some of the CoW implications
render.data = rVals[['data']][rVals[['data']][['Species']] %in% c(rVals[['baseline']],input$rows),]
# here manipulate render.data
# and then continue with plot
ggplot(data=render.data,
aes(x=Petal.Width, y = as.numeric(Sepal.Width), colour = Species,group=Species)
) +
labs(x="Hypothetical X", y="Hypothetical X") +
geom_line()
})
observeEvent(input$base,{
rVals[['baseline']]=input$rows
})
observeEvent(input$reset,{
rVals[['baseline']]=NULL
})
}
shinyApp(ui, server)

How do I create a reactive plot using ggplot in Shiny application

I have spent several hours trying to figure out how to generate a bar plot using ggplot2 for a shiny app I want to create. The ui works fine, however; the server function generates an empty plot.
The issue is with renderPlot function. I believe I must not be passing the reactive values properly to the aes_string arguments in ggplot.
C2 is a filtered dataset. The goal is to build a simple app in which the user selects a two variables, a dataset is filtered based upon those variables. The subsetted dataset is passed to ggplot data argument.
library(shiny)
library(dplyr)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(inputId = "Demog",label = "Factor:",choices = c("HH Income" = "Income",
"Age Group" = "Age",
"US Region" = "Region") , selected = "Age"),
selectInput(inputId = "Car",label = "VW Model:",choices = c("BEETLE" = "BEETLE",
"CC" = "CC",
"EOS" = "EOS",
"GOLF" = "GOLF",
"GTI" ="GOLF SPORTSWAGEN GTI",
"JETTA" = "JETTA",
"PASSAT" = "PASSAT",
"TIGUAN" = "TIGUAN",
"TOUAREG" = "TOUAREG") , selected = "BEETLE"),
radioButtons(inputId = "Metric",label ="Measurement Type",choices =
c("Conquest Volume Index" = "TotCmpConqVol_IDX","C/D Ratio" = "TotCmpCDRatio_IDX"), selected = "TotCmpConqVol_IDX" )
)
),
mainPanel(
tags$h1("The Bar Charts"),
tags$h2("The metrics"),
plotOutput("P1")
)
)
server <- function(input, output){
library(ggplot2)
CONQDF <- read.csv("C:/Users/Reginald/Desktop/CONQ_VW/CONQUEST2.csv")
C2 <- reactive(subset(CONQDF,input$Demog %in% levels(input$Demog)[1] & CONQDF$VW_Model == input$Car))
output$P1 <- renderPlot({
ggplot(C2(),aes_string(x="CompMake", y=input$Metric))+ geom_bar(stat = "identity")
})
}
shinyApp(ui,server)
The ui works fine, however; the server function generates an empty
plot.
This is most likely due to the fact that the function subset returns an empty dataset. In order to debug the code, first, I would print out in the console this part:
C2 <- reactive(subset(CONQDF,input$Demog %in% levels(input$Demog)[1] & CONQDF$VW_Model == input$Car))
I believe that this part is wrong because input$Demog is just a character string and not a factor. That's why levels(input$Demog) = NULL and input$Demog %in% levels(input$Demog) = FALSE. Hence, as a result, you get an empty dataset.
To check this:
output$P1 <- renderPlot({
print(C2()) # print it out to the console.
ggplot(C2(),aes_string(x="CompMake", y=input$Metric))+ geom_bar(stat = "identity")
})
If this is the case, you only need to re-think subsetting part.
It looks like your C2 function can't see CONQDF (hence the blank plot). You can add () after CONQDF in your C2 call to run that read.csv every time, but you're probably better off moving the read.csv outside your server function altogether.
So move this line
CONQDF <- read.csv("C:/Users/Reginald/Desktop/CONQ_VW/CONQUEST2.csv")
to the top of your script, just below library(dplyr). This will make shiny read that file when the page first loads, instead of every time the input is updated, and will also place the resulting dataframe into the global environment, which will mean your C2 <- call will be able to see it.
I can't easily reproduce your app, so I can't test my answer. Please let me know whether or not it helps.

Resources