I have a chart in Shiny generated with the HighCharter package. I would like to surpress the "No data to display" message which is shown when the series to be plotted is empty. In my case, the actual content of the plot is shown as a plotLines (variable age below). However, in order for HighCharter to display the plotLines, it needs data. This is the reason, why I add the line (remove that line to see what I mean):
%>% hc_series(list(data=c(), visible=FALSE, id="dummy"))
Can this be done?
Here is a sample using reprex(venue="r"): I would like that the background gradient and the plotLines are showed but the message "No data to display" should be hidden.
library(shiny)
library(highcharter)
#> Highcharts (www.highcharts.com) is a Highsoft software product which is
#> not free for commercial and Governmental use
# layout
ui <- fluidPage(highchartOutput("highchart_slider", height = "200px"))
server <- function(input, output) {
# This value comes from the backend and is variable. It is in [-100, 100]
age <- 20
output$highchart_slider <- renderHighchart({
hcSlider <- highchart() %>%
hc_chart(renderTo= "container",
defaultSeriesType = 'bar',
plotBackgroundColor=list(
linearGradient = list(x1=0, x2=1, y1=0, y2=0),
stops=list(list(0, '#bf0000'),list(0.45, '#e1e218'),
list(0.55, '#e1e218'),list(1, 'darkgreen')))) %>%
hc_yAxis(tickInterval=100, min=-100, max=100,
plotLines=list(list(
label = list(text = "title", align = 'center', verticalAlign = 'top'),
color = "black", width = 4, value = age, y = -2))
) %>%
hc_series(list(data=c(), visible=FALSE, id="dummy"))
# display plot
hcSlider
})
}
# start the app
shinyApp(ui = ui, server = server)
#' <!--html_preserve-->
#' Shiny applications not supported in static R Markdown documents
#' <!--/html_preserve-->
Your question has no reproducible example, but as I understand, you want to prevent a plot to be plotted, whenever no data is available?
I would advice looking into req()
https://shiny.rstudio.com/articles/req.html
If you want a plot to be only plotted when let's say data is available,
do:
output$plot <- renderPlot({
req(data)
...
})
req will not only stop the plot when the data is NULL or FALSE, but also when the user has no data selected
Related
this is my R code:
output$heatmap_viewed_ads <- renderPlotly({
plot_ly( x = c(1,2,3,4,5), y = casted_viewed_ads$FEED, z = as.matrix(casted_viewed_ads[2:15]), type = "heatmap",colors = "Greens" )%>%
layout(title = "#Views", xaxis=list(title="Position of Display"))})
I am plotting right here this data. I do now want to just show the matrix that is generated by
as.matrix(casted_viewed_ads[2:15])
Can someone help me please? I'm new to R. I'm using Shiny and Plotly.
Thanks!
You can use renderTable to display your matrix in the Shiny app.
Server
output$matrix <- renderTable({
yourmatrix <- as.matrix(casted_viewed_ads[2:15])
yourmatrix
})
UI
mainPanel(
plotOutput("heatmap_viewed_ads"), #you can eliminate this line if you just want to show the table
tableOutput("matrix")
)
I want to draw a Plotly graph in the Shiny App in R. I want the the functionality in such a way that I want to plot a certain number of points (say 20) in a loop.
This is my code for the Server.R :-
xAxis = vector("numeric", as.numeric(input$Generations))
yAxis = vector("numeric", as.numeric(input$Generations))
graphDF = data.frame(cbind(xAxis, yAxis))
for(i in 1 : 5)
{ output$GA = renderPlotly({
print(graphDF) # Testing
graphDF$yAxis[i] = i
graphDF$xAxis[i] = i
print(graphDF) # Testing
# Plotly functionality
p <- plot_ly(graphDF, x = graphDF$xAxis, y = graphDF$yAxis)
})
}
Any help would be most appreciated.
Kind Regards
This was more complicated than it looked. It looks like you want to iterate and create a series of plotly graphs, changing the data values as you go along.
Because the Generations slider re-initializes the vector to a new length,
and each iteration changes the state of the data being plotted, you can't just cascade reactive functions. Storing the state in a reactiveValues is a good way to handle this.
The major changes were as follows:
Added a reactiveValues to store xAxis and yAxis
Added an observeEvent to reinitialize those values when its value change
Added an "Iteration range" slider to drive the iteration (easier than a reactive timer). Note that it has an animate parameter that (probably) creates a reactive timer on its own.
Modified the plotly call to make it more conventional and avoid warnings.
The code:
library(shiny)
library(plotly)
u <- fluidPage(
titlePanel("Iterations of a plotly graph"),
sidebarLayout(
sidebarPanel(
sliderInput("Generations","Number of Generations:",
min = 1, max = 50, value = 20),
sliderInput("iter", "Iteration range:",
value = 1, min = 1, max = 1000, step = 1,
animate=animationOptions(interval=800, loop=T)),
p("To start click on the blue arrowhead")
),
mainPanel(
plotlyOutput("GA")
)
))
s <- shinyServer(function(input,output){
rv <- reactiveValues(xAxis=NULL,yAxis=NULL)
observeEvent(input$Generations,{
rv$xAxis=vector("numeric", as.numeric(input$Generations))
rv$yAxis=vector("numeric", as.numeric(input$Generations))
})
output$GA = renderPlotly({
rv$yAxis[input$iter] <- input$iter
rv$xAxis[input$iter] <- input$iter
gdf <- data.frame(xAxis=rv$xAxis, yAxis=rv$yAxis)
plot_ly(gdf, x = ~xAxis, y = ~yAxis, type="scatter",mode="markers")
})
})
shinyApp(u,s)
Because it is dynamic, you have to run it to see how it really works, but here is a screen shot after several iterations:
PROBLEM SYNOPSIS: I have a shiny app I am building where I am trying to support database calls that drive dynamic lists of choices for selectInputs and where that dynamic input drives what a ggvis plot shows. The dynamic selectInput is not correctly selected and filtering the ggvis plot
QUESTION: How can I support dynamic drop down lists while still ensuring my ggvis plot filters based on the chosen item?
PROBLEM DETAIL:
Within my Server.R file I have a reactive that grabs a slice of data from the database. The get_chunk function is a call to NEO4J that I know works:
shinyServer( function(input, output, session) {
CURRENT_CHUNK <- reactive({
#call NEO4J
chunk <- get_chunk(some_list = input$chunk)
return(chunk)
})
I also have a reactive that simply filters down the data based on the ui choices on the front end. The input$A value is the chosen value from a dynamically built dropdown list. The filter_reactive is below. NOTE: I've separated these two so I don't have to call the database all the time; only when I choose a different CHUNK. The filter reactive looks like the following:
NO_DB_REACTIVE <- reactive({
#react to current_chunk and pull back a chunk.
filter_down <- CURRENT_CHUNK()
#check for nulls
if (!is.null(chunk)) {
if (input$A != "All") {filter_down <- filter_down %>% filter(A == input$A)}
return(filter_down)
}
return(filter_down)
})
The input$A value is generated dynamically as follows within the server.R file:
# reactively /dynamically generated the choices for the channel owners
output$owner_choices <- renderUI({ selectInput("A", "FOR Owner"
, as.list(c("All",unique(CURRENT_CHUNK()[,'owner'] )))
, "All") })
I also have a reactive that generates my GGVIS plot that looks like the following:
#All of the visualizations
MY_VIS <- reactive({
# Lables for axes
yvar_name <- names(display_choices)[display_choices == input$yvar]
xvar_name <- names(cat_choices)[cat_choices == input$xvar]
#retrieving
yvar <- prop("y", as.symbol(input$yvar))
xvar <- prop("x", as.symbol(input$xvar))
CURRENT_CHUNK %>%
ggvis(x = xvar, y = yvar) %>%
layer_bars() %>%
add_axis("x", title = xvar_name, properties = axis_props(labels = list(angle = 45, align = "left", fontSize = 10))) %>%
add_axis("y", title = yvar_name) %>%
set_options(width = 900, height = 300)
})
I tried to slim this down as much as possible. There is some dynamic choosing of axes there but you get the point. Notice I currently call CURRENT CHUNK within the MY_VIS reactive. And the end of the file has these:
output$table <- renderDataTable({ NO_DB_REACTIVE() })
MY_VIS %>% bind_shiny("my_vis")
When I filter items this way I get no errors. My table filters on input$A changes and the vis does not; I want the vis to change based on what input$A is as well.
I originally tried having MY_VIS depend on NO_DB_REACTIVE. This fails as input$A is never generated. I guess because CURRENT_CHUNK never runs as it doesn't have to. Notice the output$owner_choices is generated by reacting to CURRENT_CHUNK() not NO_DB_REACTIVE().
KEY QUESTION: How can I set this up so my input$A value is available when I want to filter my ggvis plot?
I have a simple shiny app, I would like to pass the value from the selectInput as a column name of data frame and use it in ggplot. My UI code looks like that:
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("Title"),
# Sidebar with a slider input for the number of bins
sidebarLayout(
sidebarPanel(
selectInput(inputId = "yaxis",
label = "Y-axis",
choices = list("Overall Rank" = "overall_rank",
"Income Deprivation" = "income_deprivation_rank"),
selected = "income_deprivation_rank"),
selectInput(inputId = "xaxis",
label = "X-axis",
choices = list("Overall Rank" = "overall_rank",
"Income Deprivation" = "income_deprivation_rank"),
selected = "overall_rank")),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
h5("Notes"),
p("notes")
)
)
))
My server side code is vary simple, I have a SPARQL query (cut here to save the space) that creates simple data frame:
# Libs
require(shiny); require(SPARQL); require(ggplot2)
# Server function
shinyServer(function(input, output) {
# Source the data
## Define endpoint URL.
endpoint <- "http://data.opendatascotland.org/sparql.csv"
### Create Query
query.simd <- "PREFIX stats: <http://statistics.data.gov.uk/id/statistical-geography/>
(...) cut to save space (...)"
## Make the data
dta.simd<- SPARQL(url = endpoint, query = query.simd, format = "csv")$results
## Make the plot
output$distPlot <- renderPlot({
xaxis <- as.character(input$xaxis)
yaxis <- as.character(input$yaxis)
# draw the the plot
ggplot(data = dta.simd, aes(x = xaxis, y = yaxis)) +
geom_point(shape=1)
})
})
The query results in a simple data frame, resambling the extract below:
observation overall_rank income_deprivation_rank
a001 2 6
a002 10 7
a003 11 9
After compiling the app I keep on receiving the Error: object 'xaxis' not found. This leads me to believe that for whatever reason the value from the input$xaxis is not passes to the xaxis object and cannot be used in ggplot. If I decide to replace the as.character(input$yaxis) with a string corresponding to the column name, like for instance overall_rank and the other one income_deprivation_rank the app works as it should, so the problem is clearly associated with using the input$xaxis value. I tried the code with no as.character() function but got the same error message.
Wherever you would normally reference the column name as a string like input$colName, replace it with get(input$colName). This way Shiny knows to fetch the value of input$colName instead of treating it as a string.
I came across a problem while using rCharts in my Shiny application. I generate dynamically 1-3 tabPanels (depending on the user selection) and in each of them one plot is rendered. Plot may be of two types: simple (with graphics libary) or rCharts (with morris library). The whole tabsetPanel is rendered within the uiOutput component, each time an user changes his input. The type of the ui output (plotOutput for simple plot or showOutput for rCharts) is defined when a tabPanel is rendered, so the plot does have a proper environment.
And the problem: simple plots (with graphics, ggplot2 etc.) do work OK - they are displayed correctly in a tabPanel. However, when I work with application and have 2 or 3 rCharts to be displayed, it happens that one chart is not displaying - almost at all (see the images below). Of course, such a problem does not appear with simple plots.
I tried to have the output size fixed, size flexible, but the problem still exists. I have varsions of R and the libraries as follows:
> R.Version()$version.string
[1] "R version 3.0.1 (2013-05-16)"
> packageVersion("Shiny")
[1] ‘0.7.0’
> packageVersion("rCharts")
[1] ‘0.3.51’
Thank you a lot for any suggestions.
rCharts working OK:
rCharts FAIL to be dispkayed ok:
EDIT: my code below:
UI
library(shiny)
library(Epi)
shinyUI(pageWithSidebar(
headerPanel("Header"),
sidebarPanel(
checkboxInput(inputId = "checkboxInputx", label = "function: x", value = TRUE),
checkboxInput(inputId = "checkboxInputxpower2", label = "function: x^2", value = FALSE),
checkboxInput(inputId = "checkboxInput2x", label = "function: 2x", value = FALSE),
actionButton("gobutton","GO!")
),
mainPanel(
radioButtons("plottypechoice", "Choose plot type", c("simple", "rCharts")),
uiOutput("plotpanelcontent")
)
))
SERVER
library(shiny)
library(rCharts)
library(Epi)
library(reshape2)
# build data frame
x <- 1:100
df <- data.frame(x, x^2, 2*x)
names(df) <- c("x", "xpower2", "2productx")
shinyServer(function(input, output) {
# generate tabsetPanel with tabPlots with plot of selected type
output$plotpanelcontent <- renderUI({
if(input$gobutton != 0){
# collect tab names
tab.names <- vector()
if(input$checkboxInputx) tab.names <- c(tab.names, "x")
if(input$checkboxInputxpower2) tab.names <- c(tab.names, "xpower2")
if(input$checkboxInput2x) tab.names <- c(tab.names, "2productx")
print(tab.names)
# render tabs
tabs <- lapply(tab.names, function(tab.name){
# define tabPanel content depending on plot type selection
if(input$plottypechoice == "simple")
tab <- tabPanel(tab.name, plotOutput(paste0("simpleplot", tab.name)))
else
tab <- tabPanel(tab.name, showOutput(paste0("rchartplot", tab.name), "morris"))
return(tab)
})
return(do.call(tabsetPanel, tabs))
}
})
# Render simple plots
output$simpleplotx <- renderPlot({
print(plot(df[,1], df[,1]))
plot(df[,1], df[,1])
})
output$simpleplotxpower2 <- renderPlot({
print(plot(df[,1], df[,2]))
plot(df[,1], df[,2])
})
output$simpleplot2productx <- renderPlot({
print(plot(df[,1], df[,3]))
plot(df[,1], df[,3])
})
# Render rCharts
output$rchartplotx <- renderChart({
plot <- mPlot(x="x", y="x", type = "Line", data = df)
plot$set(dom = "rchartplotx")
return(plot)
})
output$rchartplotxpower2 <- renderChart({
plot <- mPlot(x="x", y="xpower2", type = "Line", data = df)
plot$set(dom = "rchartplotxpower2")
return(plot)
})
output$rchartplot2productx <- renderChart({
plot <- mPlot(x="x", y="2productx", type = "Line", data = df)
plot$set(dom = "rchartplot2productx")
return(plot)
})
})
UPDATE:
I have asked Olly Smith, an author of morris.js library, to suggest a solution and I received a following response:
Morris can't correctly draw charts when they're not displayed on screen. When using Morris in tabbed applications, you need to redraw the active chart whenever the tab selection changes. There's a redraw() method on the chart objects that each of the Morris.Line/Bar/Donut constructors return that you can use to do this. Unfortunately, it's currently undocumented, but it's a stable part of the API now so it's safe to use.
UPDATE 2. :
I followed the Ramnath suggestions and update both Shiny and rCharts libraries version:
> packageVersion("Shiny")
[1] ‘0.8.0’
> packageVersion("rCharts")
[1] ‘0.3.53’
and run the code just after restarting the R session. Unfortunately, plots seem to behave in even stranger way now. After doing actions in the following order:
set: "function: x", "rCharts", GO [OK],
add: "function: x^2" [see "not_ok_1" image attached below in the post],
add: "function: 2x" [see "not_ok_2" image attached below in the post].
I received the plot visualizations as follows:
OK
"not_ok_1" image
"not_ok_2" image