Plotly update nested argument via updatemenus - r

I would like to create a dropdown menu using updatemenus from R Plotly to be able to change the source image in a plot.
This is what I have done so far, without success:
library(plotly)
library(magrittr)
img1 <- "https://www.gravatar.com/avatar/dc04a25fbabbffc1f1b7c6a3362bfae4?s=256&d=identicon&r=PG"
img2 <- "https://www.gravatar.com/avatar/bc680ed8d2555accacebc0fe2d8c9691?s=256&d=identicon&r=PG"
plot_ly(x = 1:5, y = 1:5, type = 'scatter', mode = 'markers') %>%
layout(
images = list(
list(
source = img1,
xref = "x",
yref = "y",
x = 3,
y = 4,
sizex = 2,
sizey = 2
)
),
updatemenus = list(
list(
y = 1,
buttons = list(
list(method = "restyle",
args = list(list(images = list(list(source = img1)))),
label = "img1"),
list(method = "restyle",
args = list(list(images = list(list(source = img2)))),
label = "img2")
)
)
)
)
What am I missing?

There is probably more than one way to do this, but this works. For layout updates, you're usually going to use the method relayout. You need to provide all of the information, as well (i.e., x, y, xref, etc.).
library(plotly)
img1 <- "https://www.gravatar.com/avatar/dc04a25fbabbffc1f1b7c6a3362bfae4?s=256&d=identicon&r=PG"
img2 <- "https://www.gravatar.com/avatar/bc680ed8d2555accacebc0fe2d8c9691?s=256&d=identicon&r=PG"
imgOne = list( # create image expectations
list(
source = img1,
xref = "x", yref = "y",
x = 3, y = 4,
sizex = 2, sizey = 2))
imgTwo = list( # create image expectations
list(
source = img2,
xref = "x", yref = "y",
x = 3, y = 4,
sizex = 2, sizey = 2))
plot_ly(x = 1:5, y = 1:5, type = 'scatter', mode = 'markers') %>%
layout(
images = imgOne,
updatemenus = list(
list(
y = 1,
active = 0,
buttons = list(
list(label = "None",
method = "relayout",
args = list(list(images = c()))),
list(label = "img1",
method = "relayout",
args = list(list(images = imgOne))),
list(label = "img2",
method = "relayout",
args = list(list(images = imgTwo)))
))))
There are a few method options for updatemenus. You can read more about that here.

Related

Plotly grouped barchart : how to create buttons to display different x values R

this is my dataframe :
artists <- c("Black Waitress", "Black Pumas")
tee_x<- c(20, 0)
tee_y <- c(3, 18)
tee_z <- c (30,0)
tee_t <- c(0,35)
data2 <- data.frame(artists, tee_x, tee_y,tee_t)
And this is what I am trying to create :
fig <- plot_ly(data=data2, x = ~artists, y = ~tee_x, type = 'bar', name = 'tee_x')
fig <- fig %>% add_trace(y = ~tee_y, name = 'tee_y')
fig <- fig %>% add_trace(y = ~tee_t, name = 'tee_t')
fig <- fig %>% layout(yaxis = list(title = 'Count'), barmode = 'group',
updatemenus = list(
list(
y = 0.8,
buttons = list(
list(method = "restyle",
args = list("x", list(data2[c(1),(2:4)])),
label = "Black Waitress"),
list(method = "restyle",
args = list("x", list(data2[c(2),(2:4)])),
label = "Black Pumas")))
))
fig
I am trying to create a grouper barplot in plotly which shows, for each artist the number of tees they sold and their type. I am also trying to create buttons so that you can look at individual artists instead of both of them. However it is not working and I have no clue how to solve the problem.
Thank you
EDIT :
I have been also trying this way
product <- c("tee_X","tee_y","tee_t")
artists <- c("Black Waitress", "Black Pumas")
Black_Waitress<- c(20, 0, 0)
Black_Pumas <- c(3, 18, 0)
tee_z <- c (30,0)
tee_t <- c(0,35)
data2 <- data.frame(product, Black_Waitress, Black_Pumas)
show_vec = c()
for (i in 1:length(artists)){
show_vec = c(show_vec,FALSE)
}
get_menu_list <- function(artists){
n_names = length(artists)
buttons = vector("list",n_names)
for(i in seq_along(buttons)){
show_vec[i] = TRUE
buttons[i] = list(list(method = "restyle",
args = list("visible", show_vec),
label = artists[i]))
print(list(show_vec))
show_vec[i] = FALSE
}
return_list = list(
list(
type = 'dropdown',
active = 0,
buttons = buttons
)
)
return(return_list)
}
print(get_menu_list(artists))
fig <- plot_ly(data=data2, x = ~product, y = ~Black_Waitress, type = 'bar')
fig <- fig %>% add_trace(y = ~Black_Pumas)
fig <- fig %>% layout(showlegend = F,yaxis = list(title = 'Count'), barmode = 'group',
updatemenus = get_menu_list(artists))
fig
However the problem is that when I choose an artist in the dropdown menu I want to be shown ONLY his/her products (in other words I would like to get rid of the 0 values dynamically) Is this possible?
Without the 0 Values and Initially Blank Plot
Essentially, you need to add a trace with no data. Additionally, since visibility settings were defined, all of that requires updating (because there are more traces now).
This can be further customized, of course. Here's a basic version of what I think you're looking for.
plot_ly(data = data3, x = ~artists, y = 0, type = "bar", color = ~tees,
visible = c(T, T, T)) %>%
add_bars(y = ~values, split = ~artists, # visibility F for all here
legendgroup = ~tees, name = ~tees, visible = rep(F, times = 4),
color = ~tees) %>%
layout(
yaxis = list(title = "Count"), barmode = "group",
updatemenus = list(
list(y = .8,
buttons = list(
list(method = "restyle", # there are 7 traces now; 3 blank
args = list(list(visible = c(F, F, F, F, T, F, T))),
label = "Black Waitress"),
list(method = "restyle",
args = list(list(visible = c(F, F, F, T, F, T, F))),
label = "Black Pumas")))))
Without the 0 Values
By your request, here is a version where the zero values are removed. First, I filtered the data for the non-zero values. This changed the number of traces from 6 to 4, so that needed to be accounted for in the areas where visibility is declared.
In this version, I only commented where there was something that changed from my original answer.
library(plotly)
library(tidyverse)
artists <- c("Black Waitress", "Black Pumas")
tee_x <- c(20, 0)
tee_y <- c(3, 18)
# tee_z <- c(30,0)
tee_t <- c(0,35)
data2 <- data.frame(artists, tee_x, tee_y, tee_t)
data3 <- pivot_longer(data2, col = starts_with("tee"),
names_to = "tees", values_to = "values") %>%
filter(values != 0) # <----- filter for non-zeros
plot_ly(data = data3, x = ~artists, y = ~values, split = ~artists,
legendgroup = ~tees, name = ~tees,
visible = rep(c(F, T), times = 2), # <---- 4 traces
color = ~tees, type = "bar") %>%
layout(
yaxis = list(title = "Count"), barmode = "group",
updatemenus = list(
list(y = .8,
buttons = list(
list(method = "restyle", # 4 traces
args = list(list(visible = c(F, T, F, T))),
label = "Black Waitress"),
list(method = "restyle", # 4 traces
args = list(list(visible = c(T, F, T, F))),
label = "Black Pumas")))))
With the 0 Values
I think it will be a lot easier to use visibility than trying to change out the data. If you wanted to see one artist at a time and use the dropdown to switch between the groups, this works.
First, I rearranged the data to make this easier. When I plotted it, I used split, so that the traces were split by the values on the x-axis, along with the colors. The traces are ordered artist 1, tee_t, artist 2, tee_t... and so on. When using visibility, you need the method restyle (because it's a trace attribute) and a declaration of true or false for each trace.
library(tidyverse)
library(plotly)
data3 <- pivot_longer(data2, col = starts_with("tee"),
names_to = "tees", values_to = "values")
plot_ly(data = data3, x = ~artists, y = ~values, split = ~artists,
legendgroup = ~tees, name = ~tees, visible = rep(c(F, T), times = 3),
color = ~tees, type = "bar") %>%
layout(
yaxis = list(title = "Count"), barmode = "group",
updatemenus = list(
list(y = .8,
buttons = list(
list(method = "restyle",
args = list(list(visible = c(F, T, F, T, F, T))),
label = "Black Waitress"),
list(method = "restyle",
args = list(list(visible = c(T, F, T, F, T, F))),
label = "Black Pumas")))))

How to add multiple shapes on plot_ly slider chart?

I am trying to visualize multiple periods in a time-series/candlestick chart, highlighting certain dates by vertical lines. Similar to the sinus wave example here: https://plotly.com/r/sliders/
aval <- list(setNames(xts(matrix(data = rnorm(1:28), ncol = 4), as.Date(1:7)), c("Open","High","Low","Close")),
setNames(xts(matrix(data = rnorm(1:52), ncol = 4), as.Date(1:13)), c("Open","High","Low","Close")),
setNames(xts(matrix(data = rnorm(1:20), ncol = 4), as.Date(1:5)), c("Open","High","Low","Close")))
Looping through the list, I can achieve my desired result with respect to the vertical lines:
for (i in 1:length(aval)) {
fig <- plot_ly()
b <- data.frame(Date=index(aval[[i]]), coredata(aval[[i]]))
line <- list(type = "line", line = list(color = 'magenta'), # , dash = "dot", width = 0.5
xref = "x", yref = "paper", x0 = NA, x1 = NA, y0 = 0, y1 = 1)
l <- list(line, line)
l[[1]][['x0']] <- l[[1]][['x1']] <- b[1+1,1]
l[[2]][['x0']] <- l[[2]][['x1']] <- b[nrow(b)-1,1]
fig <- add_trace(fig, type = "candlestick", x = b[,1], open = b[,2], close = b[,5], high = b[,3], low = b[,4],
showlegend = FALSE) %>%
layout(xaxis = list(rangeslider = list(visible = F), type = "category"), shapes = l, font = list(size = 10))
fig <- fig %>% config(displayModeBar = FALSE)
print(fig)
}
However, using the slider layout, I am only able to use one vertical line, see:
n <- length(aval)
steps <- list()
fig <- plot_ly()
for (i in 1:length(aval)) {
b <- data.frame(Date=index(aval[[i]]), coredata(aval[[i]])[,c('Open','High','Low','Close')])
toggle <- ifelse(i == 1, TRUE, FALSE)
line <- list(type = "line", line = list(color = 'magenta', dash = "dot", width = 0.5),
xref = "x", yref = "paper", x0 = b[1+1,1], x1 = b[1+1,1], y0 = 0, y1 = 1)
fig <- add_trace(fig, type = "candlestick", x = b[,1], open = b[,2], close = b[,5], high = b[,3], low = b[,4],
visible = toggle, showlegend = FALSE) %>%
layout(xaxis = list(rangeslider = list(visible = F), type = "category"), shapes = line, font = list(size = 10))
step <- list(args = list('visible', rep(FALSE, length(aval))), label = i, method = 'restyle')
step$args[[2]][i] = TRUE
steps[[i]] = step
}
fig <- fig %>% layout(sliders = list(list(active = 0, steps = steps))) %>% config(displayModeBar = FALSE)
fig
Using a list of shapes, analog to my first example, does not seem to work:
steps <- list()
fig <- plot_ly()
for (i in 1:length(aval)) {
b <- data.frame(Date=index(aval[[i]]), coredata(aval[[i]])[,c('Open','High','Low','Close')])
toggle <- ifelse(i == 1, TRUE, FALSE)
line <- list(type = "line", line = list(color = 'magenta', dash = "dot", width = 0.5),
xref = "x", yref = "paper", x0 = NA, x1 = NA, y0 = 0, y1 = 1)
l <- list(line, line)
l[[1]][['x0']] <- l[[1]][['x1']] <- b[1+1,1] # as.character
l[[2]][['x0']] <- l[[2]][['x1']] <- b[nrow(b)-1,1]
fig <- add_trace(fig, type = "candlestick", x = b[,1], open = b[,2], close = b[,5], high = b[,3], low = b[,4],
visible = toggle, showlegend = FALSE) %>%
layout(xaxis = list(rangeslider = list(visible = F), type = "category"), shapes = l, font = list(size = 10))
step <- list(args = list('visible', rep(FALSE, length(aval))), label = i, method = 'restyle')
step$args[[2]][i] = TRUE
steps[[i]] = step
}
fig <- fig %>% layout(sliders = list(list(active = 0, steps = steps))) %>% config(displayModeBar = FALSE)
fig
Can anybody help me? Is this related to the visibility argument in steps, perhaps?

Switch displayed traces via plotly dropdown menu

I am working with the R programming language. I am trying to replicate this tutorial over here for my own data: https://plotly.com/r/dropdowns/
I created some fake data and made 4 plots:
#load libraries
library(plotly)
library(MASS)
library(dplyr)
# create data
x <- sample( LETTERS[1:4], 731, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25) )
y <- rnorm(731,10,10)
z <- rnorm(731,5,5)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
df <- data.frame(x,y, z, date)
df$x = as.factor(df$x)
# plot 1 : time series
aggregate = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(y))
ts_1 <- ggplot(aggregate) + geom_line(aes(x = month, y = mean, group = 1)) + theme(axis.text.x = element_text(angle = 90)) + ggtitle("time series 1")
plot_1 = ggplotly(ts_1)
#plot 2 : box plot
plot_2 <- plot_ly(df, y = ~y, color = ~x, type = "box") %>% layout(title = "boxplot")
#plot 3, 4 : scatter plots
df_1 <- df[which(df$x == "A"),]
df_2 <- df[which(df$x == "B"),]
plot_3 <- plot_ly( data = df_1, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 3")
plot_4 <- plot_ly( data = df_2, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 4")
Once these 4 plots have been created, I know how to save them together:
sub = subplot(plot_1, plot_2, plot_3, plot_4, nrows = 2)
#view result
sub
Now what I am trying to do, is have the user "toggle" (switch) between these graphs (as seen here: https://plotly.com/r/dropdowns/)
In a previous post (R: Switching Between Graphs ), I learned how to "glue" similar graphs together (e.g. 4 scatter plots). Now, I am trying to do so with different graphs (2 scatter plots, 1 time series and 1 box plot). I tried to adapt the code from the previous post to suit my example:
fig <- df %>%
add_trace(name = "A", plot_1) %>%
add_trace (name = "B" , df, y = ~y, color = ~x, type = "box") %>% layout(title = "boxplot")
add_trace (name = "C" , data = df_1, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 3") %>%
add_trace( name = "D", data = df_2, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 4") %>%
layout(xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(method = "restyle",
args = list("visible", list(TRUE, FALSE, FALSE, FALSE)),
label = "A"),
list(method = "restyle",
args = list("visible", list(FALSE, TRUE, FALSE, FALSE)),
label = "B"),
list(method = "restyle",
args = list("visible", list(FALSE, FALSE, TRUE, FALSE)),
label = "C"),
list(method = "restyle",
args = list("visible", list(FALSE, FALSE, FALSE, TRUE)),
label = "D")))))
But this produces the following errors:
Error: $ operator is invalid for atomic vectors
Error in add_data(p, data) : argument "p" is missing, with no default
Can someone please show me if it is possible to fix this problem? Instead of using the "add_trace" approach, is it somehow possible to individually call each plotly graph object by its name (e.g. subplot(plot_1, plot_2, plot_3, plot_4, nrows = 2)), "glue" all the graphs together, and then add a "toggle button" that lets the user switch between them?
(note: I need to be able to save the final result as a "html" file)
Thanks
First of all, you should take care about plots which add multiple traces (see nTracesA etc.)
Besides changing the trace visibility you'll need to seperate categorial and numerical data onto separate x and y-axes and manage their visibility, too (see xaxis2, xaxis3, xaxis4 - this also works with a single y-axis but in this case the grid isn't displayed properly)
As described in the docs:
The updatemenu method determines which plotly.js function will be used
to modify the chart. There are 4 possible methods:
"restyle": modify data or data attributes
"relayout": modify layout attributes
"update": modify data and layout attributes
"animate": start or pause an animation (only available offline)
Accordingly the following, is using the update method (a lot of repition here - needs some cleanup, but I think it's better to understand this way):
# load libraries
library(dplyr)
library(plotly)
# create data
x <- sample(LETTERS[1:4],
731,
replace = TRUE,
prob = c(0.25, 0.25, 0.25, 0.25))
y <- rnorm(731, 10, 10)
z <- rnorm(731, 5, 5)
date <- seq(as.Date("2014/1/1"), as.Date("2016/1/1"), by = "day")
df <- data.frame(x, y, z, date)
df$x = as.factor(df$x)
nTracesA <- nTracesC <- nTracesD <- 1
nTracesB <- length(unique(df$x))
plotA <- plot_ly(data = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise(mean = mean(y)),
type = 'scatter', mode = 'lines', x= ~ month, y= ~ mean, name = "plotA", visible = TRUE, xaxis = "x", yaxis = "y")
plotAB <- add_trace(plotA, data = df, x = ~x, y = ~y, color = ~ x, name = ~ paste0("plotB_", x),
type = "box", xaxis = "x2", yaxis = "y2", visible = FALSE, inherit = FALSE)
plotABC <- add_trace(plotAB, data = df[which(df$x == "A"),],
type = "scatter", mode = "markers", x = ~ y, y = ~ z,
name = "plotC", xaxis = "x3", yaxis = "y3", visible = FALSE, inherit = FALSE)
plotABCD <- add_trace(plotABC, data = df[which(df$x == "B"),], x = ~ y, y = ~ z,
type = "scatter", mode = "markers", name = "plotD", xaxis = "x4", yaxis = "y4", visible = FALSE, inherit = FALSE)
fig <- layout(plotABCD, title = "Initial Title",
xaxis = list(domain = c(0.1, 1), visible = TRUE, type = "date"),
xaxis2 = list(overlaying = "x", visible = FALSE),
xaxis3 = list(overlaying = "x", visible = FALSE),
xaxis4 = list(overlaying = "x", visible = FALSE),
yaxis = list(title = "y"),
yaxis2 = list(overlaying = "y", visible = FALSE),
yaxis3 = list(overlaying = "y", visible = FALSE),
yaxis4 = list(overlaying = "y", visible = FALSE),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(label = "A",
method = "update",
args = list(list(name = paste0("new_trace_name_", 1:7), visible = unlist(Map(rep, x = c(TRUE, FALSE, FALSE, FALSE), each = c(nTracesA, nTracesB, nTracesC, nTracesD)))),
list(title = "title A",
xaxis = list(visible = TRUE),
xaxis2 = list(overlaying = "x", visible = FALSE),
xaxis3 = list(overlaying = "x", visible = FALSE),
xaxis4 = list(overlaying = "x", visible = FALSE),
yaxis = list(visible = TRUE),
yaxis2 = list(overlaying = "y", visible = FALSE),
yaxis3 = list(overlaying = "y", visible = FALSE),
yaxis4 = list(overlaying = "y", visible = FALSE)))
),
list(label = "B",
method = "update",
args = list(list(visible = unlist(Map(rep, x = c(FALSE, TRUE, FALSE, FALSE), each = c(nTracesA, nTracesB, nTracesC, nTracesD)))),
list(title = "title B",
xaxis = list(visible = FALSE),
xaxis2 = list(overlaying = "x", visible = TRUE),
xaxis3 = list(overlaying = "x", visible = FALSE),
xaxis4 = list(overlaying = "x", visible = FALSE),
yaxis = list(visible = FALSE),
yaxis2 = list(overlaying = "y", visible = TRUE),
yaxis3 = list(overlaying = "y", visible = FALSE),
yaxis4 = list(overlaying = "y", visible = FALSE)))),
list(label = "C",
method = "update",
args = list(list(visible = unlist(Map(rep, x = c(FALSE, FALSE, TRUE, FALSE), each = c(nTracesA, nTracesB, nTracesC, nTracesD)))),
list(title = "title C",
xaxis = list(visible = FALSE),
xaxis2 = list(overlaying = "x", visible = FALSE),
xaxis3 = list(overlaying = "x", visible = TRUE),
xaxis4 = list(overlaying = "x", visible = FALSE),
yaxis = list(visible = FALSE),
yaxis2 = list(overlaying = "y", visible = FALSE),
yaxis3 = list(overlaying = "y", visible = TRUE),
yaxis4 = list(overlaying = "y", visible = FALSE)))),
list(label = "D",
method = "update",
args = list(list(visible = unlist(Map(rep, x = c(FALSE, FALSE, FALSE, TRUE), each = c(nTracesA, nTracesB, nTracesC, nTracesD)))),
list(title = "title D",
xaxis = list(visible = FALSE),
xaxis2 = list(overlaying = "x", visible = FALSE),
xaxis3 = list(overlaying = "x", visible = FALSE),
xaxis4 = list(overlaying = "x", visible = TRUE),
yaxis = list(visible = FALSE),
yaxis2 = list(overlaying = "y", visible = FALSE),
yaxis3 = list(overlaying = "y", visible = FALSE),
yaxis4 = list(overlaying = "y", visible = TRUE))))
))))
print(fig)
# htmlwidgets::saveWidget(partial_bundle(fig), file = "fig.html", selfcontained = TRUE)
# utils::browseURL("fig.html")
Some related info:
https://plotly.com/r/custom-buttons/
https://plotly.com/r/multiple-axes/
This is just a guess from the documentation but there is no add_data() call so maybe try this for your first line:
fig <- plot_ly() %>% add_data(df) %>%
See docs example:
plot_ly() %>% add_data(economics) %>% add_trace(x = ~date, y = ~pce)
A user on the Rstudio community forum provided an answer : https://community.rstudio.com/t/gluing-graphs-together-switch-toggle-between-graphs-in-r-plotly/95891/3
I am still trying to figure out how to format the axis - maybe someone could take a look at this?
#load libraries
library(plotly)
library(MASS)
library(dplyr)
# create data
x <- sample( LETTERS[1:4], 731, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25) )
y <- rnorm(731,10,10)
z <- rnorm(731,5,5)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
df <- data.frame(x,y, z, date)
df$x = as.factor(df$x)
# plot 1 : time series
aggregate = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(y))
ts_1 <- ggplot(aggregate) + geom_line(aes(x = month, y = mean, group = 1)) + theme(axis.text.x = element_text(angle = 90)) + ggtitle("time series 1")
plot_1 = ggplotly(ts_1)
#plot 2 : box plot
plot_2 <- plot_ly(df, y = ~y, color = ~x, type = "box") %>% layout(title = "boxplot")
#plot 3, 4 : scatter plots
df_1 <- df[which(df$x == "A"),]
df_2 <- df[which(df$x == "B"),]
plot_3 <- plot_ly( data = df_1, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 3")
plot_4 <- plot_ly( data = df_2, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 4")
fig = plot_ly()
fig = fig %>% add_trace(data = df %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(y)), type = 'scatter', mode = 'lines', x= ~month, y= ~mean,
name = "timeseries")
fig = fig %>% add_trace(data = df[which(df$x == "A"),], y = ~y, color = ~x,
type = "box", name = "boxplot")
fig = fig %>% add_trace( data = df[which(df$x == "B"),],
type = "scatter", mode = "markers", x = ~ y, y = ~z,
name= "graph2")
fig = fig %>% add_trace(data = df[which(df$x == "A"),], y = ~y, color = ~x,
type = "box", name = "boxplot2")
fig %>% layout(xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(method = "restyle",
args = list("visible", list(TRUE, FALSE, FALSE, FALSE)),
label = "A"),
list(method = "restyle",
args = list("visible", list(FALSE, TRUE, FALSE, FALSE)),
label = "B"),
list(method = "restyle",
args = list("visible", list(FALSE, FALSE, TRUE, FALSE)),
label = "C"),
list(method = "restyle",
args = list("visible", list(FALSE, FALSE, FALSE, TRUE)),
label = "D")))))

r-plotly Filter Button to Display All Data

I am attempting to use r-plotly to make an interactive graph. I would like there to be a button to filter by groups specified in the data. In the example below, the button works to filter the data into group 1 and group 2, but the button for "All groups" does not display all of the data. Anyone have suggestions?
df <- tibble(x = c(1, 4, 2, 7), y = c(3, 1, 8, 4), group = c(2, 1, 1, 2))
fig <- plot_ly(data = df, type = "scatter", mode = "markers") %>%
add_trace(type = "scatter", mode = "markers", x=~x, y=~y,
transforms = list(
list(
type = "filter",
target = ~group,
operation = 'in',
value = unique(df$group)
)
)
) %>%
layout(
updatemenus = list(
list(
type = 'dropdown',
active = 0,
buttons = list(
list(method = "restyle",
args = list("transforms[0].value", unique(df$group)[2]),
label = "Group 1"),
list(method = "restyle",
args = list("transforms[0].value", unique(df$group)[1]),
label = "Group 2"),
list(method = "restyle",
args = list("transforms[0].value", unique(df$group)),
label = "All groups")
)
)
)
)
fig

plotly: Updating data with dropdown selection

I am not sure if this is possible, but here is what I would like to do. I would like to update the data in a plotly plot by selecting from a dropdown menu.
As a simple example, let's assume I have a data frame
df <- data.frame(x = runif(200), y = runif(200), z = runif(200))
from which I use df$x and df$y in a scatter plot. Two scenarios of data manipulation I would like to achieve using a dropdown:
Replace df$y with df$z
Plot only the first n values of df$x and df$y
I looked at the following two examples, which I can easily reproduce:
https://plot.ly/r/dropdowns/
However, I have no idea how to pass the information regarding the data to be plotted based on the dropdown selection. For scenario 2 e.g. I have tried it with args = list("data", df[1:n,]) which did not work.
For scenario 1 the (only?) way to go (according to the examples) seems to be hiding/showing the traces respectively. Is that the only way for scenario 2 as well?
Any alternative ideas?
Update 1: Add reproducible example
So here is an example which achieve what I would like in scenario 1.
require(plotly)
df <- data.frame(x = runif(200), y = runif(200), z = runif(200))
Sys.setenv("plotly_username"="xxx") #actual credentials replaced
Sys.setenv("plotly_api_key"="xxx") #actual credentials replaced
p <- plot_ly(df, x = df$x, y = df$y, mode = "markers", name = "A", visible = T) %>%
add_trace(mode = "markers", y = df$z, name = "B", visible = T) %>%
layout(
title = "Drop down menus - Styling",
xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(method = "restyle",
args = list("visible", list(TRUE, TRUE)),
label = "Show All"),
list(method = "restyle",
args = list("visible", list(TRUE, FALSE)),
label = "Show A"),
list(method = "restyle",
args = list("visible", list(FALSE, TRUE)),
label = "Show B")))
))
plotly_POST(p)
Result here: https://plot.ly/~spietrzyk/96/drop-down-menus-styling/
This is based on the example from https://plot.ly/r/dropdowns/
However, I am wondering if one could pass the data to be plotted instead of triggering changes to the visible property of individual traces.
The one thing I tried was the following:
p <- plot_ly(df, x = df$x, y = df$y, mode = "markers", name = "A", visible = T) %>%
layout(
title = "Drop down menus - Styling",
xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(method = "restyle",
args = list("y", df$y),
label = "Show A"),
list(method = "restyle",
args = list("y", df$z),
label = "Show B")))
))
Result here: https://plot.ly/~spietrzyk/98/drop-down-menus-styling/
This approach cannot work, as the data from df$z is not posted to the grid (https://plot.ly/~spietrzyk/99/).
So I was wondering is there anyway to manipulate the data to be plotted based on dropdown selection, beyond plotting all traces and than switching the visible property by dropdown selections.
Is this what you were after?
require(plotly)
df <- data.frame(x = runif(200), y = runif(200), z = runif(200))
p <- plot_ly(df, x = ~x, y = ~y, mode = "markers", name = "A", visible = T) %>%
layout(
title = "Drop down menus - Styling",
xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.7,
buttons = list(
list(method = "restyle",
args = list("y", list(df$y)), # put it in a list
label = "Show A"),
list(method = "restyle",
args = list("y", list(df$z)), # put it in a list
label = "Show B")))
))
p
On the top of #jimmy G's answer.
You can automatically create the buttons so that you don't have to manually specify every single variable you want in the plot.
library(plotly)
df <- data.frame(x = runif(200), y = runif(200), z = runif(200), j = runif(200), k = rep(0.7, 200), i = rnorm(200,0.6,0.05))
create_buttons <- function(df, y_axis_var_names) {
lapply(
y_axis_var_names,
FUN = function(var_name, df) {
button <- list(
method = 'restyle',
args = list('y', list(df[, var_name])),
label = sprintf('Show %s', var_name)
)
},
df
)
}
y_axis_var_names <- c('y', 'z', 'j', 'k', 'i')
p <- plot_ly(df, x = ~x, y = ~y, mode = "markers", name = "A", visible = T) %>%
layout(
title = "Drop down menus - Styling",
xaxis = list(domain = c(0.1, 1)),
yaxis = list(title = "y"),
updatemenus = list(
list(
y = 0.7,
buttons = create_buttons(df, y_axis_var_names)
)
))
p
Hope you find it useful.

Resources