Using Proxy Interface in Plotly/Shiny to Dynamically Change Data

Using Proxy Interface in Plotly/Shiny to dynamically change data

Strangely enough addTracesdoes not work with only one point but works with two points. To make it work you could add the same point twice. So you could try this:

ui <- fluidPage(
actionButton("update", "Test"),
plotlyOutput("graphe")
)

server <- function(input, output, session) {
output$graphe <- renderPlotly({
p <- plot_ly(type="scatter",mode="markers")
p <- layout(p,title="test")
p <- add_trace(p, x=0,y=0,name="ABC_test",mode="lines+markers")
})

observeEvent(input$update, {
plotlyProxy("graphe", session) %>%
plotlyProxyInvoke("deleteTraces", list(as.integer(1))) %>%
plotlyProxyInvoke("addTraces", list(x=c(0, 0),y=c(1, 1),
type = 'scatter',
mode = 'markers'))
})
}

shinyApp(ui, server)

How to dynamically add AND remove overlay from plotly histogram in shiny

Edit: @FreyGeospatial clarified, that he wants to add/remove traces (I was confused of the wording using overlay).

The easiest way to dynamically add and remove traces is to create a data.frame in long format providing a category column.

In plot_ly you can use split or color to create traces based on this column.
To remove traces you can filter categories from a reactive dataset and re-render the plot:

library(shiny)
library(plotly)

DF <- data.frame(values = rnorm(2500), category = rep(LETTERS[1:5], each = 500))

ui <- fluidPage(
selectizeInput(inputId = "barmode",
label = "barmode",
choices = c("group", "overlay", "stack"),
selected = "overlay"),
selectizeInput(inputId = "category",
label = "category",
choices = unique(DF$category), selected = LETTERS[1:3], multiple = TRUE),
plotlyOutput("myPlot")
)

server <- function(input, output, session) {

filteredDF <- reactive({
DF[DF$category %in% input$category,]
})

output$myPlot <- renderPlotly({
fig <- plot_ly(data = filteredDF(), x = ~ values, split = ~ category, alpha = 0.6, type = "histogram")
fig <- fig %>% layout(barmode = input$barmode)
fig
})

}

shinyApp(ui, server)

result

As an alternative to re-rendering the plot you could use plotlyProxy and the addTraces JS function please see my answer here. This is faster than re-rendering but less intutive using plotly's R API.


Please run:

install.packages("listviewer")
schema()

and navigate:
object ► traces ► bar ► layoutAttributes ► barmode

To find the barmode description:

default: group

Determines how bars at the same location coordinate are displayed on
the graph. With stack, the bars are stacked on top of one another
With relative, the bars are stacked on top of one another, with
negative values below the axis, positive values above With group,
the bars are plotted next to one another centered around the shared
location. With overlay, the bars are plotted over one another, you
might need to an opacity to see multiple bars.

Update plotly data (chloropleth) in R shiny without re-rendering entire map

For anyone else who comes across this post later, I found a solution.

It turns out that you can change data using the restyle method in plotlyProxyInvoke, as shown below.

library(shiny)
library(dplyr)
library(plotly)
library(readr)
library(rjson)

zip_geojson <- fromJSON(file="https://raw.githubusercontent.com/hms1/testData/main/zip3_2.json")
plot_data <- read_csv(file="https://raw.githubusercontent.com/hms1/testData/main/plot_data.csv")
mapboxToken <- "pk.eyJ1IjoiaG1vcmdhbnN0ZXdhcnQiLCJhIjoiY2tmaTg5NDljMDBwbDMwcDd2OHV6cnd5dCJ9.8eLR4FtlO079Gq0NeSNoeg"

ui <- fluidPage(

sidebarLayout(
sidebarPanel(
sliderInput("multip",
"n:",
min = 1,
max = 10,
value = 1),
actionButton("Remove", "Remove Trace")
),

mainPanel(
plotlyOutput("cPlot")
)
)
)

server <- function(input, output, session) {

output$cPlot <- renderPlotly({

plot_ly(type = "choroplethmapbox", geojson = zip_geojson) %>%
layout(
mapbox = list(
style = "light",
zoom = 3,
center = list(lon = -95.7129, lat = 37.0902)
)
) %>%
config(mapboxAccessToken = mapboxToken)

})

plotproxy <- plotlyProxy("cPlot", session, deferUntilFlush = FALSE)

observeEvent(input$multip, {

plot_data_i <- plot_data %>%
mutate(log_count = case_when(log_count <= input$multip ~ log_count * input$multip,
TRUE ~ log_count))

plotproxy %>%
plotlyProxyInvoke("restyle", list(z = list(plot_data_i$log_count),
locations = list(plot_data_i$zip)))
})
}

shinyApp(ui = ui, server = server)

How to add a new trace while removing the last one?

Based on what you described, it sounds like you want to add a trace and remove the most recent trace added at the same time when the button is pressed. This would still leave the original plot/trace that you started with.

I tried simplifying a bit. The first plotlyProxyInvoke will remove the most recently added trace (it is zero-indexed, leaving the first plotly trace in place).

The second plotlyProxyInvoke will add the new trace. Note that the (x, y) pair is included twice based on this answer.

library(shiny)
library(plotly)

A <- 1:5
B <- c(115, 406, 1320, 179, 440)
data <- data.frame(A, B)

ui <- fluidPage(plotlyOutput("fig1"),
numericInput("A",
label = h5("A"),
value = "",
width = "100px"),
numericInput("B",
label = h5("B"),
value = "",
width = "100px"),
actionButton("action3", label = "Add to plot"),
)

server <- function(input, output, session) {

fig <- plot_ly(data, x = A, y = B, type = 'scatter', mode = 'markers')

output$fig1 <- renderPlotly(fig)

observeEvent(input$action3, {
plotlyProxy("fig1", session) %>%
plotlyProxyInvoke("deleteTraces", list(as.integer(1)))
plotlyProxy("fig1", session) %>%
plotlyProxyInvoke("addTraces",
list(x = c(input$A, input$A),
y = c(input$B, input$B),
type = 'scatter',
mode = 'markers')
)
})

}

shinyApp(ui,server)

Shiny app to show simulation: how to re-write using plotly

For efficient changes to a plotly object you should take a look at plotlyProxy, which avoids re-rendering the entire plot. Here are some streaming examples.

Here is what I think you are after - btw. you sould avoid calling your reactiveValues "session", because session is an optional argument to the server function (which is needed for plotlyProxy).

library(shiny)
library(plotly)

ui <- fluidPage(titlePanel('1D Brownian Motion'),
sidebarLayout(
# panel with all inputs
sidebarPanel(
# param set-up
numericInput('mean', 'mean', 0, step = 1),
numericInput('sd', 'sd', 1, step = 0.5, min = 0.0001),

# buttons to start, stop, reset
fluidRow(
column(3, actionButton('go', 'Go')),
column(3, actionButton('stop', 'Stop')),
column(3, actionButton('reset', label = 'Reset'))
)
),

# plot panel
mainPanel(
plotlyOutput('bmtrack', height = '250px'),
plotlyOutput('bmmax', height = '250px')
)
))

server <- function(input, output, session) {
# reactive to store all reactive variables
waits <- reactiveValues(x = 0, xmax = 0, tt = 0, timer = reactiveTimer(Inf))

# function to move simulation forward
forward <- function() {
waits$x <- waits$x + rnorm(1, input$mean, input$sd)
waits$xmax <- max(waits$xmax, waits$x)
waits$tt <- waits$tt + 1
}

# when go button is pressed
observeEvent(input$go, {
waits$timer <- reactiveTimer(100)
observeEvent(waits$timer(), {
forward()
})
})

# when stop button is pressed
observeEvent(input$stop, {
waits$timer <- reactiveTimer(Inf)
})

# when reset button is pressed
observeEvent(input$reset,{
waits$x <- 0
waits$xmax <- 0
waits$tt <- 0
})

# generate initial "empty" plot
initial_plot <- plot_ly(
x = 0,
y = 0,
type = 'scatter',
mode = 'lines',
line = list(color = '#000000',
width = 3)
)

# render initial plot and assign to both outputs
output$bmmax <- output$bmtrack <- renderPlotly({
input$reset # rerender when reset is pressed
initial_plot
})

# create plotlyProxy objects for both plotly outputs
bmtrack_proxy <- plotlyProxy("bmtrack", session)
bmmax_proxy <- plotlyProxy("bmmax", session)

# manipulate plots via plotlyProxy objects (without rerendering)
observe({
plotlyProxyInvoke(bmtrack_proxy, "extendTraces", list(x = list(list(waits$tt)), y = list(list(waits$x))), list(0))
})

observe({
plotlyProxyInvoke(bmmax_proxy, "extendTraces", list(x = list(list(waits$tt)), y = list(list(waits$xmax))), list(0))
})

}

shinyApp(ui, server)

Result



Related Topics



Leave a reply



Submit