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)
Related
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.
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 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.
I am relatively new to Shiny and Plotly and have the following code snippet:
#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
library(plotly)
library(odbc)
library(DBI)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Demo"),
#Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 0,
max = 100,
value = 70)
),
# Show a plot of the generated distribution
mainPanel(
tabPanel("Heading", plotlyOutput("tbTable"))
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output, session) {
QueriedData <- reactive({
connn <- DBI::dbConnect(odbc::odbc(),.connection_string = "XXX", uid = "AB", pwd = "CD")
lat_rec.df <- dbGetQuery(connn, "PQR")
dbDisconnect(connn)
lat_rec.df1
})
output$tbTable <- renderPlotly({
plot_ly(QueriedData(),x = ~TotalCount, y = ~MyScore, type = 'scatter', mode = 'markers')
})
}
# Run the application
shinyApp(ui = ui, server = server)
As you can see above, I am plotting a scatter plot of my dataframe which I have read from the Database (as mentioned in the reactive function). I have a couple of questions here:
I want to use the slider bar input as my Y Axis (MyScore). How do I do that? I am currently unable to link slider bar (bins) into my plotly graph. I want the scatter plot to update as per the slider input.
I am slightly confused about reactive functions. Does it mean that each time, I change the slider bar, the DB is going to get called (in reactive function)? How does it work?
If I have other Database tables to read and plot in other areas, do I include it in the reactive function? Please advice.
Thanks in advance for all your help! Cheers!
My solutions/answers to your three questions.
1.As you want to know how to control Y axis with sliderInput below code explains how to do it.
library(shiny)
library(plotly)
library(DBI)
library(pool)
pool <- dbPool(drv = RMySQL::MySQL(),dbname = "db",host = "localhost",username = "root",password = "psw", port = 3306)
data <- dbGetQuery(pool, "SELECT * FROM testTable;")
ui <- fluidPage(
titlePanel("Demo"),
sidebarLayout(
sidebarPanel(
sliderInput("bins", "Number of bins:", min = 0, max = 100, value = 70)
),
mainPanel(
tabPanel("Heading", plotlyOutput("tbTable"),
plotOutput("basicPlot") # Added extra as an Example for 3rd question
)
)
)
)
server <- function(input, output, session) {
QueriedData <- reactive({
df <- data[data$total <= input$bins,] # filtering datafarme based on sliderInput
return(df)
})
output$tbTable <- renderPlotly({
plot_ly(QueriedData(), x = ~count, y = ~total, type = 'scatter', mode = 'markers')
})
# Added extra as an Example for 3rd question
output$basicPlot <- renderPlot({
data_for_plot <- dbGetQuery(pool, "SELECT * FROM dummyTable WHERE uid = 2018;")
plot(x = data_for_plot$category, y = data_for_plot$performance, type = "p")
})
}
shinyApp(ui = ui, server = server)
2.For reactivity it is better to fetch the table into a dataframe once, then place that dataframe in reactive environment. So that you can avoid multiple database calls. You can check in above code for the same.
3.Using of reactive environment purely depends on the requirement when you want to have interactivity with your shiny application. If you want to fetch the data from other tables and use in different plots, then no need to place your database connection string in reactive environment. Just query the database according to your requirement like in above code.
I have used shiny for several small scale project and am now giving a try to the shinydashboard package which looks rather promising. I also want to integrate interactive plot using plotly (although other libraries can be considered in the future).
I have no problem running examples integrating plotly in shiny (example) but face problems when attempting to achieve a similar results with shinydashboard.
For example, the code below (app.R) is not working properly.
library(shiny)
library(shinydashboard)
library(plotly)
library(ggplot2)
data(movies, package = "ggplot2")
minx <- min(movies$rating)
maxx <- max(movies$rating)
#######
####### UI
#######
ui <- dashboardPage(
############# Header
dashboardHeader(title = "Test"),
############# Sidebar
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard"))
)
),
############# Dashboard body
dashboardBody(
# Boxes need to be put in a row (or column)
fluidRow(
box(plotOutput("plot1"), width=6, height=500),
box(plotOutput("plot2"), width=6, height=500)
)
)
)
#######
####### Server
#######
server <- function(input, output, session) {
output$plot1 <- renderPlot({
# a simple histogram of movie ratings
p <- plot_ly(movies, x = rating, autobinx = F, type = "histogram",
xbins = list(start = minx, end = maxx, size = 2))
# style the xaxis
layout(p, xaxis = list(title = "Ratings", range = c(minx, maxx), autorange = F,
autotick = F, tick0 = minx, dtick = 2))
})
output$plot2 <- renderPlot({
hist(movies$rating, col="blue")
})
}
shinyApp(ui, server)
The page is supposed to display two similar plots: one generated with plotly, the other with R base. The second one is displayed properly but the plotly one is displayed in Rstudio viewer panel. If I run the App on a terminal using the runApp() function, one webpage opens for the dashboard and another one using only for the plotly interactive plot.
I have tried to create some reactive plots (plots change in function of the content of some shiny controls such as slide bars) and the plot opened either in the viewer or another browser window/tab is updated.
So everything seems to work, the only problem is that the plotly plot is not inserted in the dashboard but in a different location (viewer or other tab), which, of course, is a problem.
Despite of my research, I could not find a solution to the problem (or even people mentioning it...). Any clue?
Check again the tutorial carefully, I think you need to replace in the ui
box(plotOutput("plot1"), width=6, height=500)
by
box(plotlyOutput("plot1"), width=6, height=500)
And in the server just replace
output$plot1 <- renderPlot({
......
by
output$plot1 <- renderPlotly({
....