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)
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:
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()
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')
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)
And with cla()
:
for index, data in enumerate(x):
ax.cla()
ax.plot(data)
Related Topics
Creating New Shape Palettes in Ggplot2 and Other R Graphics
Include Text Control Characters in Plotmath Expressions
Shiny Rcharts Multiple Chart Output
Dygraph in R Multiple Plots at Once
Converting to Date in a Character Column That Contains Two Date Formats
How to Rearrange an Order of Matches Between Two Data Frames
How to Place Legends at Different Sides of Plot (Bottom and Right Side) with Ggplot2
R Xts: .001 Millisecond in Index
R Converting from Datetime to Date
R Subtract Value for the Same Id (From the First Id That Shows)
Can Sparklyr Be Used with Spark Deployed on Yarn-Managed Hadoop Cluster
How to Use Tidyr to Fill in Completed Rows Within Each Value of a Grouping Variable
Accessing Y Columns with Duplicated Names in J of X[Y, J] Merges
Unexpected Symbol Error in Parse(Text = Str) with Hyphen After a Digit
Multiple Y Axis for Bar Plot and Line Graph Using Ggplot
Ggplot2: Problem with X Axis When Adding Regression Line Equation on Each Facet