How to set independent parameters for subplots in Plotly?

Iโ€™m working with Plotly in Python to create a figure with two subplots, each containing a density contour plot. I want to set different bin sizes (nbinsx and nbinsy) for each subplot. However, it seems that setting these parameters for one subplot affects the other, and Iโ€™m unable to have independent bin sizes for each.

Hereโ€™s a minimal working example:

import plotly.graph_objs as go
from plotly.subplots import make_subplots
import plotly.express as px
import pandas as pd

# Create some dummy data
df_plot = pd.DataFrame({
    'g_w1': [i for i in range(30)],
    'w1_w2': [i*0.5 for i in range(30)],
    'bp_g': [i*2 for i in range(30)],
    'g_rp': [i*0.3 for i in range(30)],
    'type': ['typeA']*15 + ['typeB']*15
})

# Create a subplot with 1 row and 2 columns
fig = make_subplots(rows=1, cols=2)

# First density contour plot for 'crossmatches'
fig_crossmatches = px.density_contour(df_plot, x="g_w1", y="w1_w2", color='type', nbinsx=28, nbinsy=28)
# Add the 'crossmatches' plot to the first subplot
for trace in fig_crossmatches.data:
    fig.add_trace(trace, row=1, col=1)

# Second density contour plot for 'no crossmatches'
fig_nonmatches = px.density_contour(df_plot, x="bp_g", y="g_rp", color='type')
# Add the 'no crossmatches' plot to the second subplot
for trace in fig_nonmatches.data:
    fig.add_trace(trace, row=1, col=2)

# Attempt to update the bin sizes for the second subplot
fig.update_traces(selector=dict(row=1, col=2), nbinsx=128, nbinsy=128)

# Update the layout if needed
fig.update_layout(autosize=False, width=1500, height=600)

# Show the figure
fig.show()

When I run this code, the nbinsx and nbinsy for the second subplot do not seem to take effect. Iโ€™ve tried using update_traces but to no avail. How can I set independent bin sizes for each subplot in Plotly?

@NeStack Here you are trying to update a trace defined by plotly.express, and in this case you should call thefor_each_trace() method, instead of fig.update_traces:

#fig.update_traces(selector=dict(row=1, col=2), nbinsx=128, #nbinsy=128)
fig.for_each_trace(
    lambda trace: trace.update(nbinsx=128, nbinsy=128) if trace.name == "typeB" else (),
)
2 Likes