display of mapview object in shiny - r

I’m trying to have two spatial plots side-by-side in shiny, and I was suggested a powerful function, sync of mapview. sync allows to have multiple maps for comparison, a great feature, but unable to figure out integrating or calling its output in shiny. I have gone through ‘mapview for shiny’ and other related links mapview/shiny. The former suggested using renderMapview and mapviewOutput, however it did not work, i.e., no map being displayed. Please see the reproducible code. Also, I tried using #map slot of mapview object in renderLeaflet and calling it via leafletOutput - did not work. In both cases, a shiny window pops up and does not display anything. However, do see the following message in the command window: Warning in spCheckObject(x) : Columns CCN_1 in attribute table contain only NA values and are dropped. - it is related to the data base and confirms that mapview command is being executed but does not provide any leads on absence of plots. Greatly appreciate suggestions or clues on displaying mapview geneated plots in shiny.
library(shiny)
library(mapview)
ui <- fluidPage(
mapviewOutput("samplemap"),
p()
)
server <- function(input, output, session) {
output$samplemap <- renderMapview({
mapview(gadmCHE)
})
}
shinyApp(ui, server)

Related

R Shiny Plots changing without update button being pressed

I'm attempting to design a Shiny App where the user changes several inputs, then presses a "Plot" button to generate new visualizations. Currently, I have the a data object being generated in an eventReactive tied to the "Plot" button, with that data then getting fed into the renderPlot functions.
The framework seems to work, except that the plots will change whenever the inputs are changed. This often leads to errors in the plots, as different inputs load in different data. Pressing the "Plot" button after changing the inputs will cause the correct plots to render, but I'm trying to find a way to ensure that the plots don't change ever until that button is hit.
I believe the solution is a use of the "isolation" function, and I've tried that just about everywhere. However, none of these attempts have been successful. Below is a (simplified) setup of my code.
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# several selectInput options
actionButton('plot', label = 'Plot')
)
mainPanel(
plotOutput('outputPlot', height = '3in'),
)
)
)
server <- function(input, output) {
plotData <- eventReactive(input$plot, {
# load various data and organize into a list
return(data.list)
})
outPutPlot <- renderPlot({
plot.data <- plotData()
# manipulate data based on the specific plot, then generate
return(plot)
)
}
You’re right that you’d need to isolate() all reactive dependencies other
than plotData(). Without having a complete runnable example, it’s not
possible to point out where this might have gone wrong. However, it may be
easier to wrap the renderPlot() call in bindEvent(), which will isolate
everything. You just pass the expressions you want to depend on in other
arguments.
So try something like this:
bindEvent(renderPlot({ ... }), plotData())

Play audio by clicking on ggplot/plotly scatter plot

I've created a scatter plot with ggplot2 and would like to link the data points with corresponding sound files. In a shiny app it should then be possible to click on or hover over a data point to play the sound file. While I manage to get the plot into a shiny app, I am struggling with the inclusion of tags$audio, as described here, into the plot.
library(shiny)
library(plotly)
ui <- fluidPage(
plotlyOutput('scatter')
)
server <- function(input, output) {
output$scatter <- renderPlotly({
ggplotly(p)
})
}
shinyApp(ui = ui, server = server)
The plotly plot displays a tooltip with the info per data point, among others also the URL for the sound file. See the working example here: https://chart-studio.plotly.com/~petergi/1.
The ggplot2 code contains the URL information in the aes 'text'.
p <- ggplot(without_outliers) +
aes(x = T2, y = T1, label = labels, col = next_label,
text = paste0("URL: ", "https://www.yyyy.zz/audio/", tolower(bundle), ".mp3"))
Any hint to how to bring an audio player to the scatter plot's data points in shiny would be highly appreciated.
In the meantime, I found a working solution in using the R package ggiraph, which enhances ggplot2 with tooltip and onclick functionalities, when used in a shiny application. In a nutshell, a geom_point_interative call can have an onClick argument, which in turn then is a call to a Javascript function to play the audio (without opening a new window or a player).
library(ggplot2)
library(ggiraph)
library(shiny)
p <- ggplot(mtcars, aes(wt, mpg))+
geom_point_interactive(onclick="var audio= new Audio(\"https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3\"); audio.play();")
x <- girafe(ggobj = p)
To allow for all different data points in a data frame to be associated with their corresponding audio files, the data frame should be modified to contain a new column with the individual javascript code to play the audio.
An example shiny app can be found here.
Thank you Peter, I managed to get this working with help from your pointers. I know this is a late response but I hope it helps if someone else runs into a similar issue. First, I recommend reviewing the examples shared above.
I managed to get something like this working. However, instead of defining the audio and playing it with the onclick argument, I created a separate javascript file and sourced it through the shiny applet.
I created a separate file called fileNames.js where I defined each variable. Using the example above with only one audio file, this would be: var audio= new Audio("https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3");.
In the R shiny applet, I changed the onclick argument in geom_point_interactive() to the javascript code to play the audio file. In your example, the string would be simply audio.play();. For whatever reason passing the multi-line javascript code to the onclick argument didn't work for me.
Early in the ui call, I included includeScript(path = "fileNames.js") to source the javascript into the shiny app.
Here's another helpful example in case someone stumbles upon this thread as I did: https://www.ardata.fr/en/post/2019/05/24/whats-up-ggiraph/

R Shiny - dataset load in a first chunk doesn't exist in a second chunk ...?

I have a strange error in a shiny app I built with the library learnr. An error "Object not found" about an object I just loaded and just visualized (meaning the object exists no ?)
Although I don't have a reproducible example, some of you will maybe understand what is creating the error :
I have a first chunk {r load} that loads a dataset. There is no error here, I can even visualize the dataset (screenshot below)
Then I have a second chunk, where I would like to manipulate the dataset. But it tells me dataset doesn't exist ! How it could be possible, I just visualized it one chunk before ?! ...
I don't understand how a dataset could be exists in a chunk, and not in another. Does it mean the dataset isn't loaded in the global environment ? Is it a problem with the learnr library ?
Maybe someone will have an idea, or something I could test. Thank you in advance.
EDIT:
The problem is about the environment/workspace. In the first chunk, even if I load the dataset, it is not store in the environment. I tested the function ls() in a second chunk, and it tells me there is no object in the workspace. The loaded dataset is not here, I don't know why ...
In my opinion, shiny doesn't store any data. You have to pass it manually from one chunk to other as follow (only adding the code snippet from server):
server <- function(input, output, session) {
output$heat <- renderPlotly({
Name<-c("John","Bob","Jack")
Number<-c(3,3,5)
Count<-c(2,2,1)
NN<-data.frame(Name,Number,Count)
render_value(NN) # You need function otherwise data.frame NN is not visible
# You can consider this as chunk 1
})
render_value=function(NN){
# Here your loaded data is available
head(NN)
# You can consider this as chunk 2
})
}
}
shinyApp(ui, server)
You can find full code here: Subset a dataframe based on plotly click event
OR
Create global.R file as suggested here and follow this URL: R Shiny - create global data frame at start of app

Dropdown menu with R outputs using Shiny in R Markdown

I am totally new to Shiny, so first, apologize my inexperience.
I am writing a dynamic report using R Markdown, and I have several plots that deserve being shown dynamically.
Let's work with the mtcars dataset, and let's create 4 plots:
plot1 <- plot(mtcars$mpg)
plot2 <- plot(mtcars$cyl)
plot3 <- plot(mtcars$hp)
plot4 <- plot(mtcars$qsec)
So, how can I create a dropdown menu with these four plots being displayed accordingly?
I mean your example is the simplest shiny example I have ever seen on stackoverflow. I suggest you take a bit of time doing the tutorial, then you try building your own app and if you're stuck come back here :)
To learn shiny I recommend Rstudio's tutorial. After learning and forgetting everything again I advise you to use the wonderful cheatsheet provided by Rstudio.
The app.r looks like this:
library(shiny)
library(plotly)
### ui.r
ui <- fluidPage(selectInput('my_dropdown','Choose Column',colnames(mtcars)),
plotOutput('my_plot')
)
### server.r
server <- function(input, output) {
output$my_plot <- renderPlot(
plot(mtcars[,input$my_dropdown],ylab=input$my_dropdown,xlab='value')
)
}
shinyApp(ui,server)
Just for the sake of completeness. This kind of graph could be created using plotly as well. The advantage is that you can use this in a standalone html. The disadvantage is that dropdowns with plotly are quite code-intensive. The tutorial for plotly is here: https://plot.ly/r/dropdowns/

Update Shinygooglevis chart without full reload

Is it possible to change the data of a googlevis chart (any of them!) without forcing a full reload of the page/chart?
Current code that gives a very undesirable flicker when the map is being reloaded:
shinyServer(function(input, output, session) {
observe({
print("Reloading..")
invalidateLater(update_freq*1000, session)
data <- loadDataFiles()
output$gvis <- renderGvis(mapPlot(data)) //mapPlot returns a new gvisGeoChart
})
Ideally I'd just reload my markers, not the chart itself.
The googleVis Shiny bindings need to be rewritten to fix this problem. In the meantime I have prototyped some ideas here that you might want to check out; you can install it using devtools::install_github("jcheng5/googleCharts") and see the example here. It is pretty rough but you won't get the flickering and instability that currently occurs with googleVis + shiny.

Resources