Is there a way to link user input (x-axis, y-axis, colour etc) to the gganimate graph in R shiny? So that when the user selects a different input (x-axis, y-axis, colour, etc.) from the drop-down list. gganimate graph will be filled with different x-axis, y-axis, colour, etc. so that it can be changed accordingly?
The coding I tried as below. And there is error due to the variable name I saved in UI (xValue, yValue, colorValue etc which are putting in ggplot function) does not apply in the Serve...
The idea of UI code come from here: https://shiny.rstudio.com/articles/layout-guide.html
And it would display sth like this:
library(shiny)
library(shinythemes)
library(palmerpenguins)
library(gganimate)
library(dplyr)
library(tidyr)
library(ggplot2)
library(gapminder)
data(package = 'palmerpenguins')
ui <- fluidPage(
navbarPage(
"Animated penguins data",
tabPanel("Navbar 2",
##########
imageOutput('plot'),
hr(),
fluidRow(
column(3,
h4("Diamonds Explorer"),
sliderInput('sampleSize', 'Sample Size',
min=1, max=nrow(penguins), value=min(1000, nrow(penguins)),
step=500, round=0),
br(),
checkboxInput('jitter', 'Jitter'),
checkboxInput('smooth', 'Smooth')
),
column(4, offset = 1,
xValue -> selectInput('x', 'X', names(penguins)),
yValue -> selectInput('y', 'Y', names(penguins), names(penguins)[[2]]),
colorValue -> selectInput('color', 'Color', c('None', names(penguins)))
),
column(4,
rowValue -> selectInput('facet_row', 'Facet Row', c(None='.', names(penguins))),
columnValue -> selectInput('facet_col', 'Facet Column', c(None='.', names(penguins)))
)
)
#########
),
) # navbarPage
) # fluidPage
The idea of serve come from here: How to create and display an animated GIF in Shiny?
The server is sth. like this
# Define server function
server <- function(input, output) {
##########################################
output$plot <- renderImage({
# A temp file to save the output.
# This file will be removed later by renderImage
outfile <- tempfile(fileext='.gif')
# now make the animation
p = myPenguins %>%
ggplot(
aes(xValue, yValue, color = colorValue)) +
geom_point() +
#geom_line() +
facet_grid(rows = vars(rowValue), cols = vars(columnValue))+
theme_bw()+
#theme_minimal() +
transition_time(year)+
labs(title = "Year: {frame_time}")+
view_follow()#+
anim_save("outfile.gif", animate(p)) # New
# Return a list containing the filename
list(src = "outfile.gif",
contentType = 'image/gif')
}, deleteFile = TRUE)
################################################################
}
shinyApp(ui = ui, server = server)
Your code is still far from minimal and I don't have many of the packages you reference, but I think the following will illustrate the techniques that will allow you to do what you want. I've based my code on the diamonds dataset, which is part of ggplot2.
Your problem is due to the fact that Shiny input widgets (generally) return strings, whereas ggplot functions expect symbols as their argument. This is a feature of the tidyverse's use of non-standard evaluation (NSE).
As a result, the interface between Shiny and the tidyverse can be perplexing when you first come across it. One solution is to use the bang-bang operator (!!) and the sym function.
The following app displays a faceted scatter plot in which the user has complete control over the variables that
are plotted on the x axis
are plotted on the y-axis
define the colours of the plotted points
define the facet rows
define the facet columns
library(shiny)
library(tidyverse)
ui <- fluidPage(
selectInput("x", "X variable:", names(diamonds)),
selectInput("y", "Y variable", names(diamonds), selected="price"),
selectInput("colour", "Colour: ", names(diamonds), selected="color"),
selectInput("facetRows", "Facet rows: ", names(diamonds), selected="clarity"),
selectInput("facetCols", "Facet columns", names(diamonds), selected="cut"),
plotOutput("plot")
)
server <- function(input, output) {
output$plot <- renderPlot({
diamonds %>%
ggplot() +
geom_point(aes(x=!!sym(input$x), y=!!sym(input$y), colour=!!sym(input$colour))) +
facet_grid(rows=vars(!!sym(input$facetRows)), cols=vars(!!sym(input$facetCols)))
})
}
shinyApp(ui = ui, server = server)
Note that the diamonds dataset is quite large and a poor choice of variables for any of the five roles I mention above can lead to lengthy delays!
I think this provides an answer to your question, but I'm not entirely sure because of the many disparate features in your code (eg saving a GIF file, use of gganimate, reference to gapminder) that do not seem relevant to the question of using UI inputs in a call to renderPlot. If I haven't given you what you want, please refine your question and code so that they reference only the elements that are critical to the fundamental issue.
This post will help you construct a minimal reproducible example.
Related
I am building a shinyApp to display COVID-19 data. I have a file in long format that displays the day, county, positive cases, recoveries, and deaths. I am attempting to make the app where a user can select a county from a drop down menu and it will display 3 graphs of positives, recoveries, and deaths on the page. The graphs will have x-axis be dates and y-axis as a variable. Attached is the script I have so far. I have tried many different approachers, but I have no idea what to do. I am still learning R and have no prior experience with ShinyApp. Any advice or help would be appreciated. I think I have the ggPlot and output/UI right, the server logic is what is throwing me for a loop. Even just a link to a good guide would be nice. Thanks!
7/23/2020: I have updated the code. I looked in ggplot some. When I run the app, I now have the dropdown menu I wanted, but the graphs are displaying. When I create the ggplot in the console to make sure the code works on its own, I am missing the middle protion of the graph? Any ideas/fixes?
library(shiny)
library(dplyr)
library(tidyr)
library(plotly)
library(ggplot2)
library(rsconnect)
df <- read.csv("C:/Users/Nathan May/Desktop/Research Files (ABI)/Covid/Data For Shiny/Appended_File/Appended_Scraped_Files.csv") #INSERT PATH SINGLE FILE OPTION
datapos <- df[c(2,6,3)]
rsconnect::setAccountInfo(name='nathanjmay', token='A3CF4CC3DE0112B8B9F8D0BA429223D3', secret='TNwC9hxwZt+BffOhFaXD3FQsMg3eQnfaPGr0eE8S')
#UI
ui <- fluidPage(
titlePanel("COVID-19 in Arkansas Counties"),
fluidRow(
column(
width=4,
selectizeInput("County", label=h5("County"), choices= data$Counties, width="100%")
)),
fluidRow(
plotOutput(outputId = "Positive")
),
fluidRow(
plotOutput(outputId = "Recoveries")
),
fluidRow(
plotOutput(outputId = "Deaths")
),)
#SERVER
server= function(input, output) {
data <- reactive({
datapos %>% filter(County == input$County)
#GGPLOT2 for Positive
output$Positive -> renderPlot(ggplot(data=datapos, aes(x=Day, y=Positive)) +
geom_bar(stat="identity"))
#Recoveries
output$Recoveries -> renderplot()
#Deaths
output$Deaths -> renderplot()
})
}
shinyApp(ui=ui, server=server)
You're assigning all reactive expressions to the data object in the server logic, look at where you close the curly bracket. So everything get wrapped into data and nothing about your plotOutput, i.e. output$Positive, output$Recoveries, output$Death are specified in your server logic. Also the way to use reactive() feel a little awkward at first. Here's my super simply app to illustrate what you ought to do wrt to using reactive(). Again notice where you open and close the curly bracket and parentheses.
So the chain of reactions defined here are: input$state >> dat via reactive() >> output$dummy via renderPlot().
library(shiny)
library(dplyr)
library(ggplot2)
#### Fake data
df <- data.frame(state = rep(c("FL", "GA"), each = 2),
x = rnorm(4),
y = rnorm(4))
#### UI
ui <- fluidPage(
titlePanel("Old Faithful Geyser Data"),
sidebarLayout(
selectInput("state", "Choose a state:",
list(`Florida` = "FL",
`Georgia` = "GA")
),
mainPanel(
plotOutput("dummy")
)
)
)
#### Server
server <- function(input, output) {
## Essential dat is the filtered df
dat <- reactive({
df %>%
filter(state == input$state)
})
## Use dat() to access the filtered df instead of dat
output$dummy <- renderPlot({
ggplot(dat()) +
geom_point(aes(x = x, y = y))
})
}
# Run the application
shinyApp(ui = ui, server = server)
i have the following shiny application:
Dataset:(https://www.kaggle.com/rush4ratio/video-game-sales-with-ratings)
library(shinythemes)
library(shiny)
library(ggplot2)
ui = navbarPage(theme = shinytheme("united"),"Video Games Dashboard",
tabPanel("Dashboard",
sidebarLayout(
sidebarPanel(
selectInput(inputId = "dataset",
label = "Choose a dataset:",
choices = colnames(data)),
),
mainPanel(
plotOutput(outputId = "ggPlot"),
plotOutput(outputId = "ggPlot2"),
)
)
),
tabPanel("Summary",
)
)
server <- function(input, output) {
output$ggPlot <- renderPlot({
ggplot ( data=data,aes(x=Global_Sales, y=input$dataset)) +
geom_bar(stat="identity" ,fill="steelblue") +
coord_flip() +
theme_minimal()
})
output$ggPlot2 <- renderPlot({
ggplot ( data=data,aes(x=Global_Sales, y=Platform)) +
geom_bar(stat="identity" ,fill="steelblue") +
theme_minimal()
})
}
shinyApp(ui = ui, server = server)
Which looks like this:
As you can see I want to do the same in the first plot("ggPlot") like in the second plot("ggPlot2") just that the first plot is reactive and you can select every column of the datatable to display it in the plot.
However, I get this message all the time:
Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON.
Does anybody know how to fix this? Is this approach even possible?
Thanks!
This warning appears when there's a single item on one of the two axes - see this shiny issue.
But your code does not produce the plot you expect: input$dataset is the name of a column of the data, hence it is a string, and then when you do aes(x = Global_Sales, y = input$dataset), the y argument of aes is not set to a variable of the data, it is set to a string. So you have a single item on the y-axis, hence the warning.
To set the arguments of aes to some variables of the data when you have the names of these variables, you can use aes_string:
aes_string(x = "Global_Sales", y = input$dataset)
I am trying to add graph for the output which i have generated using shiny. I am getting error for graph generation. Can someone please have a look and assist. The bar graph parameters are calculation based outputs generated from calculations.
server
output$graph<- renderPlotly({
plotly( x= c(as.numeric(input$contract), round(frateperton()), differencerate()),
y= c('Contract Rate', 'ZBC Rate', 'Difference'),
name = "Zero Based Rate Chart",
type = "bar")
})
UI
plotlyOutput("graph"),
First of all, two remarks on your post :
it is not reproducible, see here to learn what a reproducible example is and how to make one
clearly you haven't searched enough. Typing "r shiny plotly output" in any search engine gives several potential solutions (here for example).
To avoid duplicated posts, please consider these two points next time.
Now, here's the answer (using iris data since your example is not reproducible):
library(shiny)
library(plotly)
ui <- fluidPage(
selectInput("choice", "Choose", choices = names(iris), selected = NULL),
plotlyOutput("graph")
)
server <- function(input, output, session){
output$graph <- renderPlotly({
plot_ly(iris, x = ~get(input$choice), y = ~Sepal.Length, type = 'scatter', mode = 'markers')
})
}
shinyApp(ui, server)
I am having trouble creating a shiny app that creates a dynamic cross tab where one of the variables can be changed.
That is, I would like to create an app that creates a cross tab that shows the percentage of students that passed against each characteristic, as well as displaying this in a bar plot.
The bar plot is no problem. I cannot figure out how to vary the input into the cross tab.
The output$my_table section in the server object is where the problem is.
Any assistance would be greatly appreciated
library(shiny)
library(ggplot2)
students <- data.frame(Passed = c("Y","Y","Y","Y","Y","Y","N","N"), Gender = rep(c("Male","Female"), each = 4),
Subject = rep(c("Maths","Science"), times = 4),Campus =c(rep(c("Victoria"), times = 7), "NSW"))
ui <- fluidPage(
titlePanel("Percentage Passed by Characteristic"),
sidebarLayout(sidebarPanel(
selectInput(
"Characteristic",
"Student characteristic",
choices = colnames(students)[!colnames(students) %in% c("Passed")],
selected = colnames(students)[2]
)
),
mainPanel(
tabPanel("Plot",
fluidRow(
plotOutput("barplot"),
verbatimTextOutput("summary"))
),
tabPanel("Summary",
tableOutput("my_table"))
)
))
server <- function(input, output) {
output$barplot <- renderPlot({
var <- input$Characteristic
gg <-
ggplot(students, aes_string(x = var, fill= "Passed"))
gg <- gg + geom_bar(position = "Stack")
gg
})
output$my_table <- renderTable({
var <- input$Characteristic
prop.table(table(students$Passed, students$var),1)
})
}
# Create Shiny object
shinyApp(ui = ui, server = server)
The problem is that students$var refers to a column literally named "var", whereas you want the column named by the value of var: students[[var]].
This is addressed the question "access data frame column using variable", and answered in the last sentence of the winning answer. access data frame column using variable
I diagnosed the problem by running your code in an interactive R session, setting var to Gender, then running the prop.table(... line, which gives the error:
Error in table(students$Passed, students$var) :
all arguments must have the same length
The next problem you'll face is formatting the resulting prop.table, but that deserves another question.
For simplicity I will only include the parts of the code that I am having issues with. This code pulls a large data set from a data base and creates tabs with different analyses. I am having issues with making my x variable reactive for ggplot graphs. If I define the x variable inside aes() the plot shows up fine but once I create a reactive input that substitutes my variable then ggplot has troubles defining the x variable. The variables I want to be able to switch are: "assay_plate_label" and "assay_read_on" from my data set.
ui.r
library(shiny)
shinyUI(fluidPage(
# Header or Title Panel
titlePanel(title = h4("HTS QC analysis", align="center")),
sidebarLayout(
# Sidebar panel
sidebarPanel(
numericInput("pg_number", "Plate Group", 4552),
actionButton('process', 'Process Plate Group Data')
),
# Main Panel
mainPanel(
tabsetPanel(type="tab",
tabPanel("Box Plot All",
selectInput('x_axis', "Choose the X axis", choices= c("Assay Plate Label"= "assay_plate_label", "Assay Date"= "assay_read_on")),
plotOutput("deviation"))
)
)
)
)
)
server.r
shinyServer(function(input, output){
x_label <- reactive({
switch(input$x_axis,
"assay_plate_label" = assay_plate_label,
"assay_read_on"= assay_read_on)
})
read.csv("table_na")
[Here is a sample of the data with the variables I use in this plot ][1]
output$deviation <- renderPlot({
table_na$assay_plate_label <- as.character(table_na$assay_plate_label)
ggplot(table_na, aes(x_label(), y=raw_assay_value, group=as.character(x_label()))) +
geom_boxplot() +
theme(axis.text.x = element_text(angle = 90, hjust = 3, vjust= 0)) +
xlab("Plate Label")+
ylab(table_na$plate_type_name)+
geom_boxplot(outlier.colour = "red", outlier.size= 1.5)+
ggtitle("All Plates Box Plot")
})
})
}
)
I had to cut down on most of the unnecessary code to make it understandable, but the code that relates to the problem it self is all here.
Difficult to know without being able to run the code, but try aes_string instead of aes.