I want to have a figure with two subplots which are both updated using the same x axis slider with plotly.express.
I have successfully done a single subplot with a slider using a command like:
import plotly.express as px
px.line(plot_df, x='context', y='probability',animation_frame='trial',animation_group='t', color="t", range_y=[0,1])
but I have no idea how to extend it to having two subplots controlled by the same slider or if this is possible at all. I can obviously add another subplot in the same manner but then the frames will not update synchronously. Any suggestions? Thank you.
EDIT
Question wasn't very clear so I am providing example data and extra description:
# Example Data for plot A
npi = 8
nc = 4
data = np.zeros([npi,nc,t])
for c in range(nc):
data[:,c,:] = np.tile(np.arange(npi).reshape(npi,1),t) + np.random.normal(0,2,size=[npi,t])
pols = np.arange(npi)
ts = np.arange(t)
cs = np.arange(nc)
mi = pd.MultiIndex.from_product([pols, cs, ts], names=['policy', 'context', 'trial'])
df = pd.Series(index=mi, data=data.flatten())
df = df.reset_index().rename(columns = {0:'probability'})
# Desired animation for plot A
px.line(df, x='policy', y='probability',animation_frame='trial',animation_group='context', color="context")
# Example Data for plot B
t = 10
nc = 6
tau = 4
data = np.zeros([nc,tau,t])
for ti in range(tau):
data[:,ti,:] = np.tile(np.arange(nc).reshape(nc,1),t) + np.random.normal(0,2,size=[nc,t])
conts = np.arange(nc)
ts = np.arange(t)
taus = np.arange(tau)
mi = pd.MultiIndex.from_product([conts, taus, ts], names=['context', 'timepoint', 'trial'])
df = pd.Series(index=mi, data=data.flatten())
df = df.reset_index().rename(columns = {0:'probability'})
# Desired animation for plot B
px.line(df, x='context', y='probability',animation_frame='trial',animation_group='timepoint', color="timepoint")
I want a figure where subplot A and B are plotted next to each other and controlled by the same "trial" slider so I can see their evolution side by side.
fig1
is first figure, fig2
is second figureimport plotly.graph_objects as go
# integrate the two figures, putting second figure on separate axis
fig = go.Figure(
data=[t for t in fig1.data] + [t.update(xaxis="x2", yaxis="y2") for t in fig2.data],
frames=[
go.Frame(
name=fr1.name,
data=[t for t in fr1.data]
+ [t.update(xaxis="x2", yaxis="y2") for t in fr2.data],
)
for fr2, fr1 in zip(fig2.frames, fig1.frames)
],
layout=fig1.layout,
)
# now config axes appropriately
fig.update_layout(
xaxis_domain=[0, 0.49],
xaxis2={"domain": [0.51, 1], "matches": None, "title":{"text":fig2.layout.xaxis.title.text}},
yaxis2={"matches":"y"},
showlegend=False,
)
import pandas as pd
import numpy as np
import plotly.express as px
# Example Data for plot A
t = 10
npi = 8
nc = 4
data = np.zeros([npi,nc,t])
for c in range(nc):
data[:,c,:] = np.tile(np.arange(npi).reshape(npi,1),t) + np.random.normal(0,2,size=[npi,t])
pols = np.arange(npi)
ts = np.arange(t)
cs = np.arange(nc)
mi = pd.MultiIndex.from_product([pols, cs, ts], names=['policy', 'context', 'trial'])
df = pd.Series(index=mi, data=data.flatten())
df = df.reset_index().rename(columns = {0:'probability'})
# Desired animation for plot A
fig1 = px.line(df, x='policy', y='probability',animation_frame='trial',animation_group='context', color="context")
# Example Data for plot B
t = 10
nc = 6
tau = 4
data = np.zeros([nc,tau,t])
for ti in range(tau):
data[:,ti,:] = np.tile(np.arange(nc).reshape(nc,1),t) + np.random.normal(0,2,size=[nc,t])
conts = np.arange(nc)
ts = np.arange(t)
taus = np.arange(tau)
mi = pd.MultiIndex.from_product([conts, taus, ts], names=['context', 'timepoint', 'trial'])
df = pd.Series(index=mi, data=data.flatten())
df = df.reset_index().rename(columns = {0:'probability'})
# Desired animation for plot B
fig2 = px.line(df, x='context', y='probability',animation_frame='trial',animation_group='timepoint', color="timepoint")
fig2