I am using Plotly to generate multiple bar charts based on a dropdown menu in R. My dataset contains hundreds of variables, and I am able to create the dropdown menu automatically thanks to this function I found here :
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(var_name) #'Show %s',
)
},
df
)
}
However, I am struggling to automatically add a line for each bar chart based on the variable selected in the dropdown menu. The dropdown menu itself is generated successfully, but I can't seem to find a way to add a line for each selected variable.
Here's an example dataset I am using:
structure(list(YW = structure(1:58, .Label = c("47-2021", "48-2021",
"49-2021", "50-2021", "51-2021", "52-2021", "1-2022", "2-2022",
"3-2022", "4-2022", "5-2022", "6-2022", "7-2022", "8-2022", "9-2022",
"10-2022", "11-2022", "12-2022", "13-2022", "14-2022", "15-2022",
"16-2022", "17-2022", "18-2022", "19-2022", "20-2022", "21-2022",
"22-2022", "23-2022", "24-2022", "25-2022", "26-2022", "27-2022",
"28-2022", "29-2022", "30-2022", "31-2022", "32-2022", "33-2022",
"34-2022", "35-2022", "36-2022", "37-2022", "38-2022", "39-2022",
"40-2022", "41-2022", "42-2022", "43-2022", "44-2022", "45-2022",
"46-2022", "47-2022", "48-2022", "49-2022", "50-2022", "51-2022",
"52-2022"), class = "factor"), X1 = c(0, 0, 0, 2, 0, 2, 0, 6,
3, 2, 2, 4, 0, 0, 0, 0, 2, 2, 2, 5, 2, 3, 2, 2, 2, 2, 0, 2, 0,
0, 2, 4, 4, 2, 2, 0, 0, 0, 2, 0, 6, 4, 4, 6, 6, 13, 2, 2, 0,
4, 2, 0, 3, 6, 4, 4, 0, 2), X2 = c(0, 0, 0, 2, 0, 2, 0, 6, 3,
2, 2, 4, 0, 0, 0, 4, 10, 2, 2, 5, 2, 3, 2, 2, 2, 2, 0, 2, 0,
0, 2, 4, 4, 2, 2, 0, 0, 2, 2, 0, 6, 6, 4, 6, 6, 13, 2, 2, 0,
4, 2, 0, 3, 6, 4, 4, 0, 2), X3 = c(0, 0, 0, 2, 0, 2, 0, 6, 2,
2, 2, 4, 2, 0, 0, 0, 2, 2, 2, 5, 2, 3, 2, 2, 2, 2, 0, 2, 0, 0,
2, 4, 4, 4, 2, 0, 0, 0, 2, 0, 6, 4, 4, 6, 6, 13, 2, 2, 0, 4,
4, 0, 3, 6, 4, 4, 0, 2), X4 = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0)), class = "data.frame", row.names = c(NA, -58L
))
p = plot_ly(data = test, x=~YW, y= ~X1 ,type ="bar", width = 1500, height = 500 )%>%
config(locale = 'fr')%>%
layout(autosize=T,
title = "",
xaxis = list(title = "Weeks"),
yaxis = list(title = "Frequency"),
updatemenus = list(
list(y = 0.7,
buttons = create_buttons(test, names(test[,!names(test) %in% "YW"])))))
I also have a separate dataframe that contains the values I want to use for the lines, where each column corresponds to a different variable. For example:
lines_x = data.frame(X1 = 5, X2 = 3, X3 = 4, X4 = 1)
My goal is to have a graph that looks like the one below, where the dropdown menu allows the user to select different variables and the lines update accordingly:
plot_ly(data = test, x=~YW, y= ~X1 ,type ="bar", width = 1500, height = 500 )%>%
add_lines(y= lines_x$X1)
How can I modify my code to achieve this? Thanks for the help !
I've modified a few things.
The function used to create your buttons: Instead of modifying one trace's y-axis, you need to modify 2. (More on that in a bit.)
The plot: added a second trace for the horizontal lines.
The layout: changed the function call to create button; added 3rd argument.
There are now three arguments: data frame for the 1st trace, data frame for the 2nd trace (the horizontal lines), and the variable names needed for the y-axis.
In the args
, instead of "y", list()
, you'll see y = list()
. Inside this list are 2 lists, the data for the first trace df[, vn]
(the bar chart) and the data for the second trace df2[, vn]
(the lines).
Plotly wasn't happy with a single value for y
when restyling, so I've called the rep
to repeat the value for the length of the data on the x-axis.
creat2 <- function(df, df2, var_n) { # 1st y df, 2nd y df, names
lapply(
var_n,
function(vn) {
button <- list(
method = 'restyle', label = paste0(vn),
args = list( # a list of 'y's (a list for each trace)
list(y = list(df[, vn], rep(df2[, vn], nrow(df)))))
)
}
)
}
I've added parentheses around the plot and the assignment operator; this allows you to update an object and print the object at the same time.
Plot specifically: add_lines
was included; arbitrarily I chose to plot X1
. I opted to set the legend to false, since it won't be meaningful, as well.
Layout specifically: In the buttons assignment, the function name has changed to creat2
and the parameters now include 2 data frames and names.
(p = plot_ly(data = test, x = ~YW, y = ~X1, type ="bar", width = 1500, height = 500 ) %>%
config(locale = 'fr') %>%
add_lines(y = lines_x$X1, showlegend = F) %>% # hide legend w/ multi traces
layout(autosize = T,
title = "",
xaxis = list(title = "Weeks"),
yaxis = list(title = "Frequency"),
updatemenus = list(list(
y = 0.7,
buttons = creat2(test, lines_x,
names(test[,!names(test) %in% "YW"]))))))
In these images, I've commented out the plot size designation. It makes it a bit easier to use my viewer pane.