I need help with a basic Shiny question. My goal is to make a simple math quiz app (What is 4 x 4?). I want to create values with one button, select a numeric answer, and then press another answer button. My problem is that i cannot find a way to access the values that are stored inside eventReactive. I have simplified the problem in the code below. The goal of this app is to ask for a number, and then to supply it. Thank you in advance!
# Goal: Fetch a number, then input that number, then receive paste("correct")/paste("incorrect)
ui <- fluidPage(
textOutput(outputId = "out"),
numericInput(inputId = "inn",
label = "",
value = 0),
actionButton("answer", "Answer"),
actionButton("question", "New Question"),
)
server <- function(input, output) {
data <- eventReactive(input$question,{
a <- sample.int(10,1)
paste("Enter",a)
})
output$out <- renderText({data()})
}
shinyApp(ui,server)
Here is what I would do
ui <- fluidPage(
textOutput(outputId = "out"),
numericInput(inputId = "inn", label = "", value = 0),
actionButton("answer", "Answer"),
actionButton("question", "New Question"),
)
server <- function(input, output, session) {
data <- reactiveValues(number = NULL)
output$out <- renderText({
if (is.null(data$number))
"Press 'New Question' button"
else
paste("Enter", data$number)
})
observeEvent(input$question, {
data$number = sample(10, 1)
})
observeEvent(input$answer, {
req(data$number, input$inn)
if (data$number == input$inn)
print("Correct")
# Do something exciting
else
print("Incorrect")
# Do something else
})
}
shinyApp(ui,server)
IMO it's good practice to keep reactive data and input/output generation separate. What I mean by that is that in the above example we use
reactiveValues to keep track of the changing data, and
observeEvent to monitor button clicks which may change specific elements of our reactive data,
renderText can print either fixed text or reactive data.
Related
I have been trying to create a R shiny dashboard including a sankey network. It is working without any problem, however some of the plots seem quite clutter due to high number of nodes and connections based on some input parameters. As an alternative solution, i am trying to implement zooming feature triggered by double click by the user, but I am getting an error of "unused element" by shiny.
The part of the ui code including double click is:
sankeyNetworkOutput("diagram",dblclick = "plot1_dblclick",
brush = brushOpts(id = "plot1_brush",resetOnNew = TRUE)
The server side code is:
output$diagram<- renderSankeyNetwork({
sankeyNetwork(Links = rv1()$links, Nodes = rv1()$nodes,
Source = "IDsource", Target = "IDtarget",
Value = "value", NodeID = "name",
iterations = 0, sinksRight=TRUE,
fontSize=13, nodePadding=20)
observeEvent(input$plot1_dblclick, {
brush <- input$plot1_brush
if (!is.null(brush)) {
ranges$x <- c(brush$xmin, brush$xmax)
ranges$y <- c(brush$ymin, brush$ymax)
} else {
ranges$x <- NULL
ranges$y <- NULL
}
})
})
I would really appreciate if I can get any help regarding to that!
Thanks!
I have a Shiny App with multiple inputs of different kinds (checkboxGroupInput, sliderInput, dateRangeInput ...) with default selected values.
I am trying to display a text message at the top of my dashboardBody if the input values are different from the default ones.
ui <- dashboardPage(
#one of the inputs
dateRangeInput(
"date_reception",
"Sélectionnez une plage de dates",
start = min(dataset_all$date_reception),
end = max(dataset_all$date_reception),
),
#the output to show if input is different from default
textOutput("warning_filters")
----------
)
server <- function(input, output) {
observeEvent(input$date_reception,
{
if ((input$date_reception[1] != min(dataset_all$date_reception)) |
(input$date_reception[2] != max(dataset_all$date_reception))) {
output$warning_filters <-
renderText({
"Warning: filters apply"
})
} else{
NULL
}
})
}
My issue is that the message is correctly displayed when I change one of the dates but does not disappear when I select again the default value (here, min(dataset_all$date_reception) or max(dataset_all$date_reception)).
I have tried playing with ignoreNULL and ignoreInit but nothing changed.
Thank you for your help!
You need to re-assign warning_filters when the condition is false. Now, the warning_filters gets set to the warning text and even though you have the function return NULL when the condition doesn't hold, you don't actually change the values of warning_filters. The code below should work.
observeEvent(input$date_reception,
{
if ((input$date_reception[1] != min(dataset_all$date_reception)) |
(input$date_reception[2] != max(dataset_all$date_reception))) {
output$warning_filters <-
renderText({
"Warning: filters apply"
})
} else{
output$warning_filters <- NULL
}
})
}
I've got a d3.js script as a R.js working perfectly when I run the preview option, but I can't get it run properly in RShiny. The inputs are not re-rendering the output and the colors are not how I set them in the js. I have a dataframe with multiple columns and I want to select the columns based on the user input to feed into the R2D3 function call in RShiny that will invoke the d3.js.
---I have the csv set up with id in one column (that will always be pulled), and value for all the other columns, even though they originally stand for values like "planet radius" etc... so I don't have to deal with changing the column names.
This code below is just the latest iteration of what I've tried. I've been through many things before like trying to make a separate reactive block for the input variable setting to a df variable which would later be called in the r2d3 function call with df(). I am out of options and out of mind at this point.
Is there something I'm missing like in the d3js script or in Rshiny? I've set up the script in the ui with includeScript() as I've seen on other posts.
the d3 script I'm using is here: https://rstudio.github.io/r2d3/articles/gallery/bubbles/
I've tried everything in my wheelhouse (which isn't much), I mean literally 20 hours spent on this and I can't get it to work.
library(shiny)
library(r2d3)
planets <- read.csv("grouped.csv")
columnList = c("Orbital Period [days]", "Orbital Semi-Major Axis [AU]",
"Eccentricity", "Planet Mass [Earths]",
"Planet Radius [Earths]", "Optical Magnitude", "Distance From
Earth [Parsecs]", "Planet Density [g/cm3]")
ui <- fluidPage(
includeScript(path = "bubbs1.js"),
selectInput(inputId = "two", label = "Data Field", choices = columnList, selected = "Distance From Earth [Parsecs]"),
d3Output("d3")
)
server <- function(input, output) {
output$d3 <- renderD3({
if (input$two == "Orbital Period [days]"){
r2d3(data = planets[,c(10,3)], script = "bubbs1.js", d3_version = "4")
}
if (input$two == "Orbital Semi-Major Axis [AU]"){
r2d3(data = planets[,c(10,4)], script = "bubbs1.js", d3_version = "4")
}
if (input$two == "Eccentricity"){
r2d3(data = planets[,c(10,5)], script = "bubbs1.js", d3_version = "4")
}
if (input$two == "Planet Mass [Earths]"){
r2d3(data = planets[,c(10,6)], script = "bubbs1.js", d3_version = "4")
}
if (input$two == "Planet Radius [Earths]"){
r2d3(data = planets[,c(10,7)], script = "bubbs1.js", d3_version = "4")
}
if (input$two == "Optical Magnitude"){
r2d3(data = planets[,c(10,8)], script = "bubbs1.js", d3_version = "4")
}
if (input$two == "Distance From Earth [Parsecs]"){
r2d3(data = planets[,c(10,9)], script = "bubbs1.js", d3_version = "4")
}
r2d3(data = planets[,c(10,9)], script = "bubbs1.js", d3_version = "4")
})
}
shinyApp(ui = ui, server = server)
Firstly, I just want the reactivity in the drop-down menu to work, and I will design the rest if you can help me with this functionality. Eventually, I want to have it be interactive (on click functions like bubble changes color, displays output text box).
i just new with rcpp, i have a problem with my rcpp function, when i directly run App, the program display error could not find function "krit". but when i run the function partially with CTRL+R and then run App the program is running well. is there a code for call R function from rcpp function in shiny that i must not run the function partially? in other words, when i directly run App the shiny will running well. this is the example code...
server
library(shiny)
library(Rcpp)
krit <- function(n){
mat <- matrix(1,n,1)
return(mat)
}
cppFunction('
NumericMatrix tes1(int n){
Function krit("krit");
NumericMatrix test = krit(n+1);
return(test);
}
')
shinyServer(function(input, output) {
output$testing <- renderUI({
list(
renderPrint(tes1(3))
)
})
})
ui
library(shiny)
shinyUI(fluidPage(
titlePanel("Shiny Text"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
uiOutput("testing")
)
)
))
This is a scoping issue regarding how shiny and Rcpp view the different environments.
What's happening is an issue with accessing the global environment using...
1) Standard Rcpp::Function magic
Rcpp::Function krit("krit");
2) Rcpp::Environment with a global pull yields a missing value.
Rcpp::Environment env = Environment::global_env();
Rcpp::Function krit = env("krit");
Error:
file3d3f43b856e05.cpp:9:45: error: no match for call to '(Rcpp::Environment) (const char [5])'
Thus, the best that can be done to resolve this scoping issue is to pass the R function that you want to use into the compiled C++ function and call it. e.g.
NumericMatrix tes1(int n, Rcpp::Function krit)
Or, you will need to modify the server.R to:
library(shiny)
library(Rcpp)
krit <- function(n){
mat <- matrix(1,n,1)
return(mat)
}
cppFunction('
// Added krit as a function pass
NumericMatrix tes1(int n, Rcpp::Function krit){
NumericMatrix test = krit(n+1);
return(test);
}
')
shinyServer(function(input, output) {
output$testing <- renderUI({
list(
# Added parameter to `tes1` to pass in krit.
renderPrint(tes1(n = 3, krit = krit))
)
})
})
Thus, you should get:
I'm able to load a saved file as an image but unable to use gganimate to do it directly. Alternate ways of rendering GIFs would be nice to know but knowing how to render gganimate specifically would really solve my problem.
library(gapminder)
library(ggplot2)
library(shiny)
library(gganimate)
theme_set(theme_bw())
ui <- basicPage(
plotOutput("plot1")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
p = ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, color = continent, frame = year)) +
geom_point() +
scale_x_log10()
gg_animate(p)
})
}
shinyApp(ui, server)
Now that there's a newer breaking version of gganimate, #kt.leap's answer is deprecated. Here's what worked for me with the new gganimate:
library(gapminder)
library(ggplot2)
library(shiny)
library(gganimate)
theme_set(theme_bw())
ui <- basicPage(
imageOutput("plot1"))
server <- function(input, output) {
output$plot1 <- 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 = ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop,
color = continent)) + geom_point() + scale_x_log10() +
transition_time(year) # New
anim_save("outfile.gif", animate(p)) # New
# Return a list containing the filename
list(src = "outfile.gif",
contentType = 'image/gif'
# width = 400,
# height = 300,
# alt = "This is alternate text"
)}, deleteFile = TRUE)}
shinyApp(ui, server)
I was dealing with the same issue and found only your question and no answers... But the way you phrased it reminded me that renderPlot is finicky:
it won’t send just any image file to the browser – the image must be generated by code that uses R’s graphical output device system. Other methods of creating images can’t be sent by renderPlot()... The solution in these cases is the renderImage() function. source
Modifying the code from that article gives you the following:
library(gapminder)
library(ggplot2)
library(shiny)
library(gganimate)
theme_set(theme_bw())
ui <- basicPage(
imageOutput("plot1"))
server <- function(input, output) {
output$plot1 <- 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 = ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop,
color = continent, frame = year)) + geom_point() + scale_x_log10()
gg_animate(p,"outfile.gif")
# Return a list containing the filename
list(src = "outfile.gif",
contentType = 'image/gif'
# width = 400,
# height = 300,
# alt = "This is alternate text"
)}, deleteFile = TRUE)}
shinyApp(ui, server)