I am using plotly for R and plotting a stacked plot for a common x variable and multiple y variables, each having their own y axis. Currently, the graph shows the all the y variable hover values for a particular x value.
I would like to show the hover values at another x value, while the previous hover is also visible.
How can I make changes to the y ranges of the stacked plot to show more ticks?
I have the following code below
Create a function for a stacked plot
plotly_stacked <- function(df, x_colName, cols){
DF <- df[, cols] %>%
tidyr::gather(variable, value, -x_colName ) %>%
transform(id = as.integer(factor(variable)))
DF$variable<- factor( DF$variable, levels = unique( DF$variable))
p <- plot_ly(data = DF, x = ~get(names(DF[1])) , y = ~value, color = ~variable, colors = "Dark2",
yaxis = ~paste0( "y",sort(id, decreasing = F))) %>%
add_lines() %>%
layout(
xaxis = list(
title = ""),
legend = list(
orientation = "h",
xanchor = "center",
x = 0.5)) %>%
plotly::subplot(nrows = length(unique(DF$variable)), shareX = TRUE)
return(p)
}
Create a data frame
df <- data.frame(
Time = c(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,
1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2),
a = c(0.01,0.02,0.03,0.04,0.05,0.06,0.07,
0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,
0.19,0.2),
b = c(0.001,0.002,0.003,0.004,0.005,0.006,
0.007,0.008,0.009,0.01,0.011,0.012,0.013,0.014,0.015,
0.016,0.017,0.018,0.019,0.02),
c = c(1e-04,2e-04,3e-04,4e-04,5e-04,6e-04,
7e-04,8e-04,9e-04,0.001,0.0011,0.0012,0.0013,0.0014,
0.0015,0.0016,0.0017,0.0018,0.0019,0.002)
)
json code for making the hover appear for all variables at the same time
#Create a vector of labels
labels <- c("xy", paste0("xy", 2: 2)) # for 4 y variables, change this from 2:4
# Convert the labels to a JSON array
labels_json <- jsonlite::toJSON(labels)
# Define the JavaScript function
js_code <- sprintf(
'function(el, x){el.on("plotly_hover", function(d) {
Plotly.Fx.hover(el.id, {xval: d.xvals[0]}, %s);
})}',
labels_json
)
Plot the variables
plotly_stacked(df, "Time", c( "Time" ,"a", "b", "c"))|>
layout(hovermode = "x") |>
htmlwidgets::onRender(js_code)
I am using plotly for R and plotting a stacked plot for a common x variable and multiple y variables, each having their own y axis. Currently, the graph shows the all the y variable hover values for a particular x value.
I would like to show the hover values at another x value, while the previous hover is also visible.
How can I make changes to the y ranges of the stacked plot to show more ticks?
I have the following code below
Create a function for a stacked plot
plotly_stacked <- function(df, x_colName, cols){
DF <- df[, cols] %>%
tidyr::gather(variable, value, -x_colName ) %>%
transform(id = as.integer(factor(variable)))
DF$variable<- factor( DF$variable, levels = unique( DF$variable))
p <- plot_ly(data = DF, x = ~get(names(DF[1])) , y = ~value, color = ~variable, colors = "Dark2",
yaxis = ~paste0( "y",sort(id, decreasing = F))) %>%
add_lines() %>%
layout(
xaxis = list(
title = ""),
legend = list(
orientation = "h",
xanchor = "center",
x = 0.5)) %>%
plotly::subplot(nrows = length(unique(DF$variable)), shareX = TRUE)
return(p)
}
Create a data frame
df <- data.frame(
Time = c(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,
1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2),
a = c(0.01,0.02,0.03,0.04,0.05,0.06,0.07,
0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,
0.19,0.2),
b = c(0.001,0.002,0.003,0.004,0.005,0.006,
0.007,0.008,0.009,0.01,0.011,0.012,0.013,0.014,0.015,
0.016,0.017,0.018,0.019,0.02),
c = c(1e-04,2e-04,3e-04,4e-04,5e-04,6e-04,
7e-04,8e-04,9e-04,0.001,0.0011,0.0012,0.0013,0.0014,
0.0015,0.0016,0.0017,0.0018,0.0019,0.002)
)
json code for making the hover appear for all variables at the same time
#Create a vector of labels
labels <- c("xy", paste0("xy", 2: 2)) # for 4 y variables, change this from 2:4
# Convert the labels to a JSON array
labels_json <- jsonlite::toJSON(labels)
# Define the JavaScript function
js_code <- sprintf(
'function(el, x){el.on("plotly_hover", function(d) {
Plotly.Fx.hover(el.id, {xval: d.xvals[0]}, %s);
})}',
labels_json
)
Plot the variables
plotly_stacked(df, "Time", c( "Time" ,"a", "b", "c"))|>
layout(hovermode = "x") |>
htmlwidgets::onRender(js_code)
Share
Improve this question
asked Feb 6 at 19:41
ACEACE
3351 gold badge3 silver badges13 bronze badges
3
|
1 Answer
Reset to default 0- "show hover on multiple x-positions". Yes, we can store previously hovered coords and print annotations (y-values) to all previously hovered x values. The code is highly customized. If you double click the graph, all annotations are removed. I hope, this is what you wanted and it makes you happy.
- Simply add
yaxis = list(nticks=20)
to your layout. Replace 20 with number of y-ticks.
Code
library(plotly)
plotly_stacked <- function(df, x_colName, cols){
DF <- df[, cols] %>%
tidyr::gather(variable, value, -x_colName ) %>%
transform(id = as.integer(factor(variable)))
DF$variable<- factor( DF$variable, levels = unique( DF$variable))
p <- plot_ly(data = DF, x = ~get(names(DF[1])) , y = ~value, color = ~variable, colors = "Dark2",
yaxis = ~paste0( "y",sort(id, decreasing = F))) %>%
add_lines() %>%
layout(
xaxis = list(
title = ""),
legend = list(
orientation = "h",
xanchor = "center",
x = 0.5),
yaxis = list(nticks=20)) %>% # adjust ticks as needed
plotly::subplot(nrows = length(unique(DF$variable)), shareX = TRUE)
return(p)
}
df <- data.frame(
Time = c(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,
1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2),
a = c(0.01,0.02,0.03,0.04,0.05,0.06,0.07,
0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,
0.19,0.2),
b = c(0.001,0.002,0.003,0.004,0.005,0.006,
0.007,0.008,0.009,0.01,0.011,0.012,0.013,0.014,0.015,
0.016,0.017,0.018,0.019,0.02),
c = c(1e-04,2e-04,3e-04,4e-04,5e-04,6e-04,
7e-04,8e-04,9e-04,0.001,0.0011,0.0012,0.0013,0.0014,
0.0015,0.0016,0.0017,0.0018,0.0019,0.002)
)
# Define the JavaScript function
js_code <-
'function(el, x) {
var previouslyHovered = [];
var annotations = [];
el.on("plotly_hover", function(d) {
var xval = Math.round(d.points[0].x * 10) / 10;
var curveIndex = d.points[0].curveNumber;
// Hover on all subplots
Plotly.Fx.hover(el.id, {xval: d.xvals[0]}, ["xy","xy2","xy3"]);
if (!previouslyHovered.includes(xval)) {
previouslyHovered.push(xval);
// Get data for all traces at this x-value
var traces = el.data;
var yaxes = ["y", "y2", "y3"];
for(var i = 0; i < traces.length; i++) {
var trace = traces[i];
var xIndex = trace.x.indexOf(xval);
if(xIndex !== -1) {
var yval = Math.round(trace.y[xIndex] * 10000) / 10000;
// Create annotation for each subplot
var annotation = {
x: xval,
y: yval,
yref: i > 0 ? `y${i + 1}` : "y",
text: yval.toString(),
showarrow: false,
ax: 0,
ay: -20,
yaxis: yaxes[i], // Specify which y-axis this annotation belongs to
font: {
size: 10
}
};
annotations.push(annotation);
}
}
// Update the plot with all new annotations
Plotly.relayout(el.id, {annotations: annotations});
}
});
// Add double-click handler to clear annotations
el.on("plotly_doubleclick", function() {
previouslyHovered = [];
annotations = [];
Plotly.relayout(el.id, {annotations: []});
});
}'
plotly_stacked(df, "Time", c( "Time" ,"a", "b", "c"))|>
layout(hovermode = "x") |>
htmlwidgets::onRender(js_code)
yaxis = list(nticks=20)
to your layout. Replace 20 with number of y-ticks. – dog Commented Feb 6 at 21:20