Missing Data When Supplying a Dual-Axis--Multiple-Traces to Subplot

Missing data when Supplying a Dual-axis--Multiple-traces to subplot

Looking at this issue on github This turned out to be a bug in plotly.

Referencing to the link above, what we need to do is explicitly defining the y axes for all the plots, all the axes. Look below for its implementation on my example:

## Creating axis layouts, explicitly for all y axes
L_Axis <- list(tickfont = list(color = "red"), overlaying = "y",
side = "right", title = "Lft")

F_Axis <- list(side = "left", title = "fmgd")

P_Axis <- list(side = "left", title = "prcp")

pp1 <- fmean1 %>% group_by(grp) %>% plot_ly() %>%
add_lines(x = ~hour, y = ~fmgd, name = "FMGD", colour = "blue") %>%
add_lines(x = ~hour, y = ~lft, name = "Lft", yaxis = "y2", colour = "red") %>%
layout( yaxis = F_Axis, #left axis
yaxis2 = L_Axis, #right axis
title = "Fbay", xaxis = list(title="Date"))

pp2 <- prcpf1 %>% plot_ly() %>%
add_bars(x=~Datetime, y=~precip, name = "prcp", yaxis = "y", colour = "green") %>%
layout(yaxis = P_Axis) #only y axis, on the left

pp <- subplot(pp1, pp2 , nrows = 2 , titleY = T, shareX = T)

Sample Image

Traces not coming up properly when working on dual axis charts with plotly R

If I understand correctly what you want, in fact, there is no problem with your code. You just need to set manually your y and y2 axis. To make it easier to visualize I simply reversed the y2 axis. If you try this:

plot_ly() %>%
add_lines(data=dtMasterWithtotals, x = ~Period_Month, y = ~A, name = "A") %>%
add_lines(data=dtMasterWithtotals, x = ~Period_Month, y = ~B, name = "B") %>%
add_lines(data=dtMasterWithtotals, x = ~Period_Month, y = ~C, name = "C", yaxis = "y2") %>%
layout(xaxis = ax, yaxis2 = list(overlaying = "y", side = "right", autorange="reversed"))

It will give you this:

Sample Image

As you can see, all three lines are visible and all three displayed the right values.

Use plotlyProxy to add multiple traces when data changes

Basically when using plotlyProxy and than plotlyProxyInvoke with "addTraces", "addTraces" is used to add more traces.
You have to create a list of lists and each inner list would contain the details of each trace.
In your case with many traces to add maybe some of the functions from the purrr package could help in creating the list of lists defining the traces.

Take a look at the code below. It is a very simplified example, adding only two traces but the lists of list approach is there.
Regarding your comment about the speed maybe you could load data only when needed and partially if your app concept allows for that...

The code:

    library("shiny")
library("plotly")
library(purrr)

ui <- fluidPage(
selectInput("dataset", "Choose a dataset:", choices = c("rock", "mtcars")),

plotlyOutput("Plot1")
)

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

output$Plot1 <- renderPlotly({plot_ly(data = rock, x = ~area,
y =~peri, mode = 'markers', type = 'scatter')})

observeEvent(input$dataset, {
if (input$dataset == "rock") {
f <- list(
family = "Courier New, monospace",
size = 18,
color = "#7f7f7f"
)
x <- list(
title = "Area",
titlefont = f,
range = c(0, max(rock$area))
)
y <- list(
title = "Peri/Perm",
titlefont = f,
range = c(0, max(rock$peri))
)
plotlyProxyInvoke(plotlyProxy("Plot1", session), "addTraces", list(list(
x = rock$area,
y = rock$peri,
type = 'scatter',
mode = 'markers',
marker = list(size = 10,
color = 'rgba(255, 182, 193, .9)',
line = list(color = 'rgba(0, 255, 0, .3)',
width = 2))
),
list(
x = rock$area,
y = rock$perm,
type = 'scatter',
mode = 'markers',
marker = list(size = 10,
color = 'rgba(255, 182, 193, .9)',
line = list(color = 'rgba(152, 0, 0, .8)',
width = 2))
))
)
plotlyProxy("Plot1", session) %>%
plotlyProxyInvoke("deleteTraces", list(as.integer(0))) %>%
plotlyProxyInvoke("relayout", list(xaxis = x, yaxis = y))
} else {
f <- list(
family = "Courier New, monospace",
size = 18,
color = "#7f7f7f"
)
x <- list(
title = "hp",
titlefont = f,
range = c(0, max(mtcars$hp))
)
y <- list(
title = "mpg/cyl",
titlefont = f,
range = c(0, max(mtcars$mpg))
)
plotlyProxyInvoke(plotlyProxy("Plot1", session), "addTraces", list(list(
x = mtcars$hp,
y = mtcars$mpg,
type = 'scatter',
mode = 'markers',
marker = list(size = 10,
color = 'rgba(255, 182, 193, .9)',
line = list(color = 'rgba(0, 255, 0, .3)',
width = 2))
),
list(
x = mtcars$hp,
y = mtcars$cyl,
type = 'scatter',
mode = 'markers',
marker = list(size = 10,
color = 'rgba(255, 182, 193, .9)',
line = list(color = 'rgba(152, 0, 0, .8)',
width = 2))
))
)
plotlyProxy("Plot1", session) %>%
plotlyProxyInvoke("deleteTraces", list(as.integer(0))) %>%
plotlyProxyInvoke("relayout", list(xaxis = x, yaxis = y))
}
})
}

shinyApp(ui, server)

Merge matplotlib subplots with shared x-axis

Look at the code and comments in it:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import gridspec

# Simple data to display in various forms
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

fig = plt.figure()
# set height ratios for subplots
gs = gridspec.GridSpec(2, 1, height_ratios=[2, 1])

# the first subplot
ax0 = plt.subplot(gs[0])
# log scale for axis Y of the first subplot
ax0.set_yscale("log")
line0, = ax0.plot(x, y, color='r')

# the second subplot
# shared axis X
ax1 = plt.subplot(gs[1], sharex = ax0)
line1, = ax1.plot(x, y, color='b', linestyle='--')
plt.setp(ax0.get_xticklabels(), visible=False)
# remove last tick label for the second subplot
yticks = ax1.yaxis.get_major_ticks()
yticks[-1].label1.set_visible(False)

# put legend on first subplot
ax0.legend((line0, line1), ('red line', 'blue line'), loc='lower left')

# remove vertical gap between subplots
plt.subplots_adjust(hspace=.0)
plt.show()

Sample Image

Common xlabel/ylabel for matplotlib subplots

This looks like what you actually want. It applies the same approach of this answer to your specific case:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6, 6))

fig.text(0.5, 0.04, 'common X', ha='center')
fig.text(0.04, 0.5, 'common Y', va='center', rotation='vertical')

Multiple plots with common axes label

Matplotlib clearing old axis labels when re-plotting data

You should clear the axes in each iteration using pyplot.cla().

You posted a lot of code, so I'm not 100% sure of the best location to place it in your code, but the general idea is to clear the axes before each new plot.

Here is a minimal demo without cla():

x = [[1,2,3], [3,2,1]]

fig, ax = plt.subplots()
for index, data in enumerate(x):
ax.plot(data)

without cla()

And with cla():

for index, data in enumerate(x):
ax.cla()
ax.plot(data)

with cla()



Related Topics



Leave a reply



Submit