Missing traces when supplying a dual-axis plot to subplot()
If I do:
library(plotly)
ay <- list(
tickfont = list(color = "red"),
overlaying = "y",
side = "right",
title = "second y axis"
)
p <- plot_ly() %>%
add_lines(x = ~1:3, y = ~10*(1:3), name = "slope of 10") %>%
add_lines(x = ~2:4, y = ~1:3, name = "slope of 1", yaxis = "y2") %>%
layout(
title = "Double Y Axis", yaxis2 = ay,
xaxis = list(title="x")
)
It plots both axis.

but if I do:
subplot(p)
I loose the secondary axis.

This doesn't seem like the intended behavior of subplot unless I am missing something. Thanks!
Try subplot(p, titleY = T)
Thanks. I tried, I see this:
so not real change from not putting that option in. Maybe it's a version issue? I am running R on windows, R version 3.3.3 (2017-03-06), and plotly appears to be version 4.5.6. Does 4.5.6 refers to the Rplotly version or to the plotly.js version?
Sorry, I mis-read the problem. This is, in fact, a bug.
such legit tile: Missing traces when supplying a dual-axis plot to subplot() :-)
Hi, I have been trying to use subplot() with dual axis, and face a similar (I think related) problem. I had built an example of my problem, and seeing that there is this open issue, I provide it here in case it is helpful.
I build two double axis plots with economics dataset:
# using "economics" dataset
# Create two 2-axis plots
# Plot 1: pop in y1 and psavert in y2
p1 <- economics %>% plot_ly() %>%
add_lines(x = ~date, y = ~pop,name="pop") %>%
add_lines(x = ~date, y = ~psavert,name="psavert",yaxis = "y2") %>%
layout(
title ="Plot1",
legend=list(x=1.1,y=1.1),
yaxis = list(title="pop"),
yaxis2 = list(side = "right", overlaying = "y",title = "psavert")
)
# Plot 2: pop in y1 and uempmed in y2
p2 <- economics %>% plot_ly() %>%
add_lines(x = ~date, y = ~pop,name="pop2") %>%
add_lines(x = ~date, y = ~uempmed,name="uempmed2",yaxis = "y2") %>%
layout(
title ="Plot2",
legend=list(x=1.1,y=1.1),
yaxis = list(title="pop"),
yaxis2 = list(side = "right", overlaying = "y",title = "uempmed")
)
If I compose a subplot with independen X axes
# Render the two together with subplot(), 2 X axes
p3 <- subplot(p1,p2,nrows=2)

If I set the shareX to TRUE:
# Render the two together with subplot(), 1 X axes
p3 <- subplot(p1,p2,nrows=2,shareX=T)

Seems like all operation on the second axis go to the same plot inside subplot. Hope this helps.
@cpsievert any updated with respect to this issue? Thanks!
Having the same issue, have a hunch the fix might be some additions to the axis handling in in subplots.R.
For example, when gathering layout attributes, yaxis2, yaxis3...yaxisN are not included in the existing list, c("mapbox", "geo", "xaxis", "yaxis"). Seems like adding the additional axis objects to this line and all others handling axes might solve this issue (utilizing generated sequences of names and regexes where possible to avoid manually typing all possible iterations of yaxis2, yaxis3...yaxisN, and y2, y3... yN).
@cpsievert Does this seem like the right path to head down? If so I'll open a PR and start working sometime this week.
lines 90-117 of subplots.R:
plots <- list()
for (i in seq_along(plotz)) {
p <- plots[[i]] <- plotz[[i]]
layoutAttrs <- c(names(p$layout), c("mapbox", "geo", "xaxis", "yaxis"))
xTraceAttrs <- sub("^x", "xaxis", sapply(p$data, function(tr) tr[["subplot"]] %||% tr[["geo"]] %||% tr[["xaxis"]] %||% "x"))
yTraceAttrs <- sub("^y", "yaxis", sapply(p$data, function(tr) tr[["subplot"]] %||% tr[["geo"]] %||% tr[["yaxis"]] %||% "y"))
missingAttrs <- setdiff(c(xTraceAttrs, yTraceAttrs), layoutAttrs)
# move to next iteration if trace references are complete
if (!length(missingAttrs)) next
# remove each "missing" trace from this plot
missingTraces <- xTraceAttrs %in% missingAttrs | yTraceAttrs %in% missingAttrs
plots[[i]]$data[missingTraces] <- NULL
# move traces with "similar missingness" to a new plot
for (j in missingAttrs) {
newPlot <- list(
data = p$data[xTraceAttrs %in% j | yTraceAttrs %in% j],
layout = p$layout
)
# reset the anchors
newPlot$data <- lapply(newPlot$data, function(tr) {
for (k in c("mapbox", "geo", "xaxis", "yaxis")) {
tr[[k]] <- sub("[0-9]+", "", tr[[k]]) %||% NULL
}
tr
})
plots <- c(plots, list(newPlot))
}
}
Another reprex:
library(plotly)
## Create a data frame with data to be plotted
S <- seq(1,100)
DF <- data.frame(S = S, A = S, B = sin(S), C = S^2)
## Create first plot, 'P_A' with trace 'A'
A_Axis <- list(side = "left", title = "Axis A")
DF %>%
plot_ly() %>%
add_lines(x = ~S , y = ~ A, yaxis = "y", name = "A",color = I("red")) %>%
layout(yaxis = A_Axis) -> P_A
## Create second plot, 'P_BC', with traces 'B' and 'C'
B_Axis <- list(side = "left", title = "Axis B")
C_Axis <- list(side = "right", title = "Axis C", overlaying = "y")
DF %>%
plot_ly() %>%
add_lines(x = ~S , y = ~ B, yaxis = "y", name = "B", color = I("blue")) %>%
add_lines(x = ~S , y = ~ C, yaxis = "y2", name = "C", color = I("green")) %>%
layout(yaxis = B_Axis,
yaxis2 = C_Axis) -> P_BC
## Create a subplot- Trace 'C' is added to the first plot instead of the second
subplot(list(P_A,P_BC),nrows = 2,titleY = TRUE, shareX = TRUE)

@msummersgill for some reason, subplot() is incorrectly changing the trace anchor numbering. To see that, take the first example and do:
diffObj::diffObj(plotly_build(p)$x$data, subplot(p)$x$data)
I'm not sure why this is happening, but if you think you have a solution, I'd love to see a pull request!
Hi, fairly new to github, coding and plotly.
Faced with a similar issue replacing
overlaying="y"
with
overlaying="y2"
in the axis definition solved my issue.
I hope it helps
Thank you very much @nc-savoy ! I feel like I still have a tenuous grasp of exactly how this is working, but that method also works for more than two plots in a subplots. (After some trial and error)
library(plotly)
## Create a data frame with data to be plotted
S <- seq(1,100)
DF <- data.frame(S = S, A = S, B = sin(S), C = S^2, D = 1/S, E = S^3 + S^3*cos(S))
## Create first plot, 'P_A' with trace 'A'
A_Axis <- list(side = "left", title = "Axis A")
DF %>%
plot_ly() %>%
add_lines(x = ~S , y = ~ A, yaxis = "y", name = "A",color = I("red")) %>%
layout(yaxis = A_Axis) -> P_A
## Create second plot, 'P_BC', with traces 'B' and 'C'
B_Axis <- list(side = "left", title = "Axis B")
C_Axis <- list(side = "right", title = "Axis C", overlaying = "y2")
DF %>%
plot_ly() %>%
add_lines(x = ~S , y = ~ B, yaxis = "y", name = "B", color = I("blue")) %>%
add_lines(x = ~S , y = ~ C, yaxis = "y2", name = "C", color = I("green")) %>%
layout(yaxis = B_Axis,
yaxis2 = C_Axis) -> P_BC
## Create third plot, 'P_DE', with traces 'D' and 'E'
D_Axis <- list(side = "left", title = "Axis D")
E_Axis <- list(side = "right", title = "Axis E", overlaying = "y4")
DF %>%
plot_ly() %>%
add_lines(x = ~S , y = ~ D, yaxis = "y", name = "D", color = I("orange")) %>%
add_lines(x = ~S , y = ~ E, yaxis = "y5", name = "E", color = I("purple")) %>%
layout(yaxis = D_Axis,
yaxis5 = E_Axis) -> P_DE
## Create a subplot
subplot(list(P_A,P_BC,P_DE),nrows = 3,titleY = TRUE, shareX = TRUE)

Trying to make sense of this example. Why are data and title for series E linked to y4 and y5, rather than both to the same y, or even both to y2? And related to that; why is series C linked to y2 (in contrast to E on y4/y5) and not for instance y3 or y5 for that matter. Are the axis counted on the left all y1 and on the right as y2 or is it a series of y1-y6?
In an approach I used, I create the panels automatically in a purrr::map structure so its hard to assign y'n' to each plots secondary axis. Coding it to append y2 to all secondary axes put all those traces and ticks on top of each other in the first row of panels in a 3*3 subplot page
facing same bug
Any more insight on how to make this work in a generic fashion?
I'm doing a lapply on a plotting function that does this different number of subplots depending on the data. (with an upper end of 5 sub plots each with their own dual axes)
I'm trying to make a similar plot related to this post and similar to the image below.
The interesting part is in the second-y-axis... it was split into two scales while the left y-axis is shared for all datasets.
- The brown line corresponds to the left-y-axis.
- The pink bars are linked to the top-right y-axis and bottom blue bars to the bottom right y-axis.
- All plots share X-axis.
Is it possible in plotly to make the left y-axis and x-axis shared?
For anyone facing this issue, this is the approach that worked for me
Setting all the yaxis arguments in add_trace() for the left y axis to "y". Setting all the yaxis arguments in add_trac() for the right y axis to "y2" Setting the "overlaying" argument in the layout for the second y axis to "y" for the first subplot, "y3" for the second, "y5" for the third and so on.
It's also important to assign the "left" attribute to the left y-axes, even though that's the default. I've found it won't work otherwise.
y <- rnorm(20,5,1)
y2 <- rnorm(20,10,2)
df <- data.frame(x,y,y2)
library(plotly)
p1 <- plot_ly() %>% add_trace(x=df$x,y=df$y,type="scatter",mode="lines",yaxis="y") %>%
add_trace(x=df$x,y=df$y2,type="scatter",mode="lines",yaxis="y2") %>%
layout(yaxis=list(side="left"),
yaxis2=list(side="right",overlaying="y"),
showlegend=FALSE)
p2 <-plot_ly() %>% add_trace(x=df$x,y=df$y+df$y2,type="scatter",mode="lines",yaxis="y") %>%
add_trace(x=df$x,y=df$y2*df$y,type="scatter",mode="lines",yaxis="y2") %>%
layout(yaxis=list(side="left"),
yaxis2=list(side="right",overlaying="y3"),
showlegend=FALSE)
p <- subplot(p1,p2,nrows = 2)

For one of my apps I had to use multiple y axis and discovered that using "anchor='free'" will lead to the issue that subplot will not display the plot at all. Hence, once can not manually rearrange the axis when you have more than 2.
It seems this bug is still alive. I needed to use the workaround provided by mabreidi to address loss of data with 4 dual yaxis subplots.
I wish this would be in the official documentation because I would otherwise have never found out about this!
@mabreidi thank you so much for this! I've literally spent more than 2 hours trying to figure out what was going on with my charts 🙏🙏🙏
Hey guys,
I was running into the same problem. Found a way to solve it (basically the same @mabreidi proposed) but the axis titles are not showing up. If you guys found a way to make them appear I'm up for the tip!
Cheers
Found it ==> subplot(........ titleY=T)
Hey, @mabreidi ! Thanks so much! This is incredible! You saved us all so much time and frustration!