Plot_ly function doesn't show a plot in shiny App - r

I am working with R version 3.6.0.
When I try to build a plot with plotly inside of a shiny App, it only shows a white space.
Also when I run the plotly function by itself, it is not shown in the Viewer, only when I open it in a new window.
library(shiny)
library(plotly)
library(datasets)
shinyApp(
ui <- fluidPage(plotlyOutput("plot1")),
server <- function(input, output) {
p <- plot_ly(mtcars, x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers')
output$plot1 <- renderPlotly({p})
}
)

Related

Plotly R- Can not adjust orientation of colorbar

I am trying to create a scatterplot within a Shiny App that has a colorbar with a horizontal orientation. Based on my reading of the Plotly reference it appears that the orientation of a colorbar can be adjusted within Layout/Coloraxis/Colorbar by setting orientation="h".
After many attempts and tweaks I can not find a way to get the colorbar to be displayed horizontally.
Any help would be appreciated.
Minimal example using the iris dataset:
library(shiny)
ui <- fluidPage(
plotlyOutput("Scatter")
)
server <- function(input, output) {
ScatterPlot<-reactive({
plot_ly(
iris,
type='scatter',
mode='lines+markers'
)%>%
add_trace(
x=~Sepal.Length,
y=~Sepal.Width,
mode='markers',
marker=list(
color=~Petal.Length,
coloraxis='coloraxis'
)
)%>%
layout(
showlegend=FALSE,
margin=list(b=50),
coloraxis=list(
colorbar=list(
orientation="h"
)
)
)
}
)
output$Scatter<-renderPlotly({ScatterPlot()})
}
shinyApp(ui = ui, server = server)

Can I programmatically control plotly zoom functionality without having to re-plot in an R shiny app?

I am trying to make a shiny app in R using Plotly plots.
I am trying to create zoom functionality in the backend of a shiny app, responsive to a click event on a plotly graph (i.e. when a point is clicked, zoom in on that point). However, the only solution I have found so far is to completely re-layout the plotly object with new view ranges.
For large plots, this is incredibly slow because shiny re-renders the entire plot, and is much slower than plotly's built-in zoom functionality on the front end (the plotly user interface buttons at the top right) when the number of data points is large. Is there a way to use the plotly zoom functionality in the backend so that the whole plotly object doesn't have to re-render to zoom?
Example:
library(plotly)
library(shiny)
ui <- fluidPage(
plotlyOutput("scatter")
)
server <- function(input, output) {
zoom_vals = reactiveValues(xrange=NA,yrange=NA)
# Plot scatter plot
output$scatter <- renderPlotly({
data <- data.frame(x=sample.int(1000,100), y = sample.int(1000,100))
x_axis = list(range = zoom_vals$xrange)
y_axis = list(range = zoom_vals$yrange)
plot_ly(data, x = ~x, y = ~y) %>% layout(xaxis=x_axis, yaxis=y_axis)
})
# Catch plot click
observeEvent(event_data("plotly_click"),{
d<-event_data("plotly_click")
zoom_vals$xrange <- c((d$x- 1),(d$x+ 1))
zoom_vals$yrange <- c((d$y- 1),(d$y- 1))
})
}
shinyApp(ui, server)
You can modify (no re-rendering) an exisiting plotly object in shiny via plotlyProxyInvoke.
To change the axis range we'll need the relayout method:
library(plotly)
library(shiny)
ui <- fluidPage(plotlyOutput("scatter"))
server <- function(input, output) {
# Plot scatter plot
output$scatter <- renderPlotly({
data <- data.frame(x = sample.int(1000, 100), y = sample.int(1000, 100))
plot_ly(data, x = ~ x, y = ~ y, type = "scatter", mode = "markers")
})
scatterProxy <- plotlyProxy("scatter")
# Catch plot click
observeEvent(event_data("plotly_click"), {
d <- event_data("plotly_click")
xrange <- c((d$x - 100), (d$x + 100))
yrange <- c((d$y - 100), (d$y + 100))
plotlyProxyInvoke(scatterProxy, "relayout", list(xaxis = list(range = xrange), yaxis = list(range = yrange)))
})
}
shinyApp(ui, server)

Inputing Data into Shiny- for a bar graph

I am trying to insert a bar graph from a dataset that I have into Shiny to make a simple bar graph of the data. This is my code thus far:
library(plotly)
library(shiny)
library(readxl)
excel_data <- read_excel(path = system.file("CHAMPdata_gender/datasets.xlxs", package = "readxl"))
ui <- fluidPage(
mainPanel(
plotlyOutput("chart")
)
)
server <- function(input, output, session) {
output$chart <- renderPlotly({
# write code here to read data from csv file
# Set x and y axis and display data in bar chart using plotly
p <- plot_ly( x = CHAMPdata_gender$X,
y = CHAMPdata_gender$Total.Respond, CHAMPdata_gender$Never, CHAMPdata_gender$Less.than.one.year, CHAMPdata_gender$One.year.or.more,
name = "Childhood data",
type = "bar")
})
}
shinyApp(ui, server)
I am currently trying to learn Shiny in R, so would appreciate all the help I can get! thanks

Set one plotly zoom to match that of another plotly zoom in Shiny

I am trying to use plotly_relayout to get the x-axis zoom limits of one plot, and apply them to another plot in Shiny. So far I can get the relevant plotly_relayout data from "plot1" (x-axis limits), transform it (from a numeric to a Date), and have it available right before plotting "plot2", however it does not actually set the zoom extents on "plot2".
In most cases, my RStudio crashes as soon as I attempt to zoom in on "plot1". Only in the small number of cases when RStudio does not crash, do I see that the "coord_cartesian" in "plot2" is not having the desired effect (after making a zoom in plot1).
I am also rather curious if the persistent crashing of my RStudio is normal given the code below, or if I may need to consider a fresh rebuild of RStudio. Any ideas on how to achieve this effect would be appreciated!
library(ggplot2)
library(plotly)
library(shinydashboard)
library(shinyWidgets)
#Data frame with dates and bogus data
a=data.frame(Date=seq.Date(as.Date("2000-01-01"),
as.Date("2000-12-31"),
"day"),
value=rnorm(366)
)
#Simple dashboard with two plots
ui <- dashboardPage(
dashboardHeader(title="Sample App"),
dashboardSidebar(
),
dashboardBody(
plotlyOutput("plot1"),
plotlyOutput("plot2")
)
)
server <- function(input, output, session){
#Create a reactive list, set zoomX1 and zoomX2 as NULL
reactiveList <- reactiveValues(zoomX1=NULL,zoomX2=NULL)
#Create a reactive function to update the reactive list every time the plotly_relayout changes
relayout_data <- reactive({
xvals=event_data("plotly_relayout",source="plot1")
if (is.null(xvals$`xaxis.range[0]`)){
} else {
reactiveList$zoomX1=as.Date(xvals$`xaxis.range[0]`,origin="1970-01-01")
reactiveList$zoomX2=as.Date(xvals$`xaxis.range[1]`,origin="1970-01-01")
}
})
#Plot1, just plot all the data
output$plot1 <- renderPlotly({
g1=ggplot(a,aes(x=Date,y=value))+
geom_point()
ggplotly(g1,source="plot1") %>% event_register("plotly_relayout")
})
#Plot 2, same as Plot1, but should set the coord_cartesian based on plot1's current zoom level taken from the event_data("plotly_relayout")
output$plot2 <- renderPlotly({
relayout_data()
g1=ggplot(a,aes(x=Date,y=value))+
geom_point()+
coord_cartesian(xlim=c(reactiveList$zoomX1,reactiveList$zoomX2))
ggplotly(g1,source="plot2")
})
}
shinyApp(ui = ui, server = server)
Actually, on my system your code is working fine.
However, you can reduce your code drastically by using plotly's subplot function and it's argument shareX. Please check the following example:
library(ggplot2)
library(plotly)
library(shinydashboard)
library(shinyWidgets)
a <- data.frame(Date = seq.Date(as.Date("2000-01-01"),
as.Date("2000-12-31"),
"day"),
value = rnorm(366))
ui <- dashboardPage(
dashboardHeader(title = "Sample App"),
dashboardSidebar(),
dashboardBody(plotlyOutput("plots", height = "80vh"))
)
server <- function(input, output, session) {
output$plots <- renderPlotly({
g2 <- g1 <- ggplot(a, aes(x = Date, y = value)) +
geom_point()
subplot(ggplotly(g1), ggplotly(g2), nrows = 2, shareX = TRUE)
})
}
shinyApp(ui = ui, server = server)

Download multiple files to one PDF shiny

I have an app with multiple pages that each have two plots and two tables. Is there a way to download all 4 as one file? A PDF would be nice but if there's a different file type that would work better, I'm open to that.
I tried following the suggestion here but I could not get it to work. I need the plots to be interactive within the app, but they can be static when downloaded. Any suggestions or is this even possible? Is there a way to even just print the main panel?
library(plotly)
library(shiny)
library(DT)
ui <- fluidPage(
mainPanel(
plotlyOutput("SepalPlot"),
DT::dataTableOutput("Sepal"),
plotlyOutput("PetalPlot"),
DT::dataTableOutput("Petal")
)
)
server <- function(input, output) {
output$SepalPlot<- renderPlotly({
plot_ly(iris, x = ~Sepal.Length, y = ~Sepal.Width, type = 'scatter', mode = 'markers')
})
sep<-data.frame(c(iris$Sepal.Length, iris$Sepal.Width))
output$Sepal<-renderDataTable({datatable(sep)})
output$PetalPlot<- renderPlotly({
plot_ly(iris, x = ~Petal.Length, y = ~Petal.Width, type = 'scatter', mode = 'markers')
})
pet<-data.frame(c(iris$Petal.Length, iris$Petal.Width))
output$Petal<-renderDataTable({pet})
}
shinyApp(ui = ui, server = server)

Resources