I´m using a shinyapp on an opensource shiny-server to display a dashboard on multiple devices. I want to give the opportunity to change the plots on all dashboards from a local PC.
If the input is altered in any session, all sessions should update their plots to this new input. How do i do this? Can i save the input in a global variable?
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
observe({
invalidateLater(10000)
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
p<<- hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$distPlot <- renderPlot({print(p)})
}
# Run the application
shinyApp(ui = ui, server = server)
You can initiate an reactiveValue in the global file and use this instead up the original input
In principal all objects initiated in the global file are shared over sessions.
Example
**UI **
library(shiny)
# Define UI for application that plots random distributions
shinyUI(pageWithSidebar(
# Application title
headerPanel("It's Alive!"),
# Sidebar with a slider input for number of observations
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot", height=250)
)
))
**Server **
library(shiny)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
# Expression that generates a histogram. The expression is
# wrapped in a call to renderPlot to indicate that:
#
# 1) It is "reactive" and therefore should be automatically
# re-executed when inputs change
# 2) Its output type is a plot
observe({
RV$bins = input$bins
})
output$distPlot <- renderPlot({
x <- faithful[, 2] # Old Faithful Geyser data
bins <- seq(min(x), max(x), length.out = RV$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
})
** Global **
RV <- reactiveValues(bins = 10)
When a user changes the number of bins the histogram will changes for all users but not the slider.
Hope this helps!!
Related
I have an output that takes user input to select which of a number of calculations to use and results in 5 numbers. That output pushes out the results of this and other calculations as an HTML table. The individual calculations are not particularly complicated, but user selections choose which of many approaches they are using, so I don't really want to replicate all that code in other outputs that are going to use just those 5 numbers.
My thought was to use the double-arrow to make those numbers available to the other outputs (in my case some plots). My goal is to generate graphs from numbers already generated in a different output, however that gets accomplished. I am not attached to the approach below, it is just where I am right now.
I ran into a number of problems just using <<- and tried a lot of things to get it to work. I won't complicate this further with all the things I tried and the problems they created.
The MRE below replicates this by calculating a number in one output that is then to be used in another output. If you enter different numbers of bins, the second output is never triggered to update to the new number. For this MRE I could of course directly use the user input to calculate that number but that is what I am trying to avoid in the real app. I also don't want to use a "Go!" button if I can avoid it since part of the fun is watching how things change in response to your various selections.
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
numericInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
textOutput("binnum")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
a_number<-0
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
a_number<<-bins[2]/5}
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$binnum<-renderText({
a_number
})
}
# Run the application
shinyApp(ui = ui, server = server)
Could you just treat bins and a_number as reactive?
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
numericInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
textOutput("binnum")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# a_number<-0
# generate bins based on input$bins from ui.R
data(faithful)
x <- faithful[, 2]
bins <- reactive({
seq(min(x), max(x), length.out = input$bins + 1)
})
a_number <- reactive({
req(bins())
-bins()[2]/5
})
output$distPlot <- renderPlot({
# draw the histogram with the specified number of bins
hist(x, breaks = bins(), col = 'darkgray', border = 'white', xlab = paste0("a = ", -bins()[2]/5))
})
output$binnum<-renderText({
a_number()
})
}
# Run the application
shinyApp(ui = ui, server = server)
I'm making a Shiny app that involves making plots from a function from a bioinformatics package that uses base R graphics. I'm building the Shiny app in RStudio Server. Since the plot can only be made with that function in that package, using ggplot2 or highcharter instead is not an option. I have no problem with saving plots made by ggplot2, but got into trouble when trying to save plots made with base R graphics. I used the answer in Downloadhander (save plot) for basic plot in shiny, but when I clicked the download button, I got "404 not found" and download was not initiated, even though that plot displayed properly within the Shiny app. Here's a modified version of RStudio's default Faithful Geyser app that can reproduce this problem:
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
downloadButton("download", "Download plot")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
p <- reactive({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$distPlot <- renderPlot(p())
output$download <- downloadHandler("foo.png",
content = function(file) {
png(file = file)
p()
dev.off()
})
}
# Run the application
shinyApp(ui = ui, server = server)
It seems that the problem is related to
png(file = file)
p()
dev.off()
not working within Shiny, since when I tried to save ggplot this way, it also gave "404 not found", while ggsave worked fine to download ggplot (though not base R plots) inside the Shiny app. Outside Shiny, the base R way to save plots works properly.
Changing p() from a reactive to a standard function solved the issue for me.
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
downloadButton("download", "Download plot")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
p <- function() {
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
}
output$distPlot <- renderPlot(p())
output$download <- downloadHandler(filename = "foo.png",
content = function(file) {
png(filename = file)
p()
dev.off()
},
contentType = "image/png")
}
# Run the application
shinyApp(ui = ui, server = server)
I want to modularise my shiny app code, by moving parts of the code in separate files. I then include the content of the file with a call to the source function: source("./www/some_code.R", local = TRUE)
It works well except for an undesired effect: the word TRUE is added just below the insert.
Could you help me understand why this happen and how I can remove this undesired text?
For a reproducible example,
create app.R:
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
source("./www/slider.R", local = TRUE)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
}
# Run the application
shinyApp(ui = ui, server = server)
and in the www folder the slider.R:
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
Just when I posted this, I saw a link to this which answer the question: displaying TRUE when shiny files are split into different folders
I thought that I did my research though... Should I delete the whole thread?
so I wrote a shiny app for importing data and plotting it using ggplot2. If I use cairo for plotting
options(shiny.usecairo=T)
(should be active by default) plots are prettier but y axis label "Oxygen consumption" miss some parts.
Plot without cairo:
Plot with cairo:
Can someone point me towards a solution or have ideas what the mistake is?
Edit: here is a minimal example:
library(shiny)
library(ggplot2)
options(shiny.usecairo=T)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
sliderInput("size",
"size:",
min = 0.1,
max = 40,
value = 15)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
res<- reactive({input$resolution})
output$distPlot <- renderPlot({
#refresh on
print(input$resolution)
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
qplot(x, breaks = bins, col = 'darkgray', ylab = "Some long string to test for errors and see what is affected")+theme_classic(base_size=input$size)
})
}
# Run the application
shinyApp(ui = ui, server = server)
So, for me it looks like some characters get cut on the right.
Edit: I narrowed this down to my windows machine, can't see it on shinyapps.io and local linux server anymore. Probably not so relevant then, since the error is only happening during development.
My Shiny script gets input from a drop down list. Based on this, I set (on the server side) a specific string (in a reactive) that should be displayed in the chart (for example as x axis title). This works only if the string contains no spaces, but no string is shown in the chart if contains spaces.
How can I get it to accept any string?
Here's my code (I modified one of the example from the Shiny tutorial to keep it as simple as possible):
# server.r
# Here the string is set depending on what was chosen by the user
shinyServer(function(input, output, session) {
label1_new <- reactive({
if (input$variable1=="pp_pmw") {label1_new <- "PP pmw"}
if (input$variable1=="perc_pp*100") {label1_new <- "PP percent"}
if (input$variable1=="formality") {label1_new <- "Formality"}
})
label1_new2 <- renderText({label1_new()})
output$distPlot <- renderPlot({
x <- faithful[, 2] # Old Faithful Geyser data
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
# xlabel1_new2() contains the string from above
hist(x, breaks = bins, col = 'darkgray', border = 'white', xlab=label1_new2())
})
})
# ui.r
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Hello Shiny!"),
# Sidebar with a slider input for the number of bins
sidebarLayout(
sidebarPanel(
selectInput("variable1", "Circle size:",
list("PP pmw" = "pp_pmw",
"PP percent" = "perc_pp*100",
"Formality" = "formality")),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
))
renderText is for use with ui.r, not for creating strings to be used in server.r
# server.r
# Here the string is set depending on what was chosen by the user
shinyServer(function(input, output, session) {
label1_new <- reactive({
if (input$variable1=="pp_pmw") return("PP pmw")
if (input$variable1=="perc_pp*100") return("PP percent")
if (input$variable1=="formality") return("Formality")
})
output$distPlot <- renderPlot({
x <- as.numeric(unlist(faithful[, 2])) # Old Faithful Geyser data
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white', xlab=label1_new())
})
})
(same ui.r)