Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

px.strip jitter doesn't work as expected due to underlying go.Box config #4563

Open
janeadams opened this issue Mar 31, 2024 · 1 comment
Open

Comments

@janeadams
Copy link

Because of the way px.strip works under the hood (generates a go.Box() with the fill color rgba set to 0,0,0,0 and the width set to None), there does not appear to be currently any way to adjust the jitter in a multi-category strip plot. One would think that adding the jitter parameter to the trace_patch would allow this parameter to pass through, but because go.Box "jitter [is] of width equal to the width of the box(es)", this makes the jitter appear to stay at 0 even when set to 1, because the width of the boxes is None. Adding a box width to the go.Box traces causes the invisible boxes to push the jittered points over to one side.

Screenshot 2024-03-31 at 1 31 09 PM

Example to reproduce:

import plotly.express as px
import plotly.graph_objects as go
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import pandas as pd
import numpy as np

# Sample Data
df = pd.DataFrame({
    'Group ID': ['A', 'A', 'B', 'B', 'C', 'C']*100,
    'Entity ID': ['M1', 'M2', 'M1', 'M2', 'M1', 'M2']*100,
    'Value': np.random.randn(600)
})

# Create a colormap
def get_hex_color(value):
    rgba_color = plt.get_cmap('coolwarm')(mcolors.Normalize(vmin=df['Value'].min(), vmax=df['Value'].max())(value))
    return mcolors.to_hex(rgba_color)
colormap = {value: get_hex_color(value) for value in df['Value'].unique()}

# ----------------------------------------

# Basic example
fig = px.strip(df, x='Group ID', y='Value', color='Value', color_discrete_map=colormap)
fig.update_traces(marker=dict(size=10, opacity=0.8, line=dict(width=1, color='DarkSlateGrey')))

# Desired behavior (this does not work):
fig.update_traces(jitter=0.1) # We would expect this to have a small amount of jitter; instead, there is a lot

# Let's try extracting the data from the plotly express figure
list(fig.data)
for box in fig.data:
    box.update(jitter=0.9) # We would expect this to have a lot of jitter, but there appears to be none
new_fig = go.Figure(fig.data)

# This is probably because the go.Box width is None; let's try adding a width param
add_width = go.Figure(fig.data).update_traces(width=20, jitter=1)

# ----------------------------------------

# Styling (ignore)
fig.update_layout(showlegend=False, title='Basic Colored Grouped Strip Plot', template='plotly_white', width=300, height=200, margin=dict(l=0, r=0, b=0, t=40), xaxis_visible=False)
fig.add_annotation(text='<b>update_traces(jitter=0.1)</b><br>We would expect this<br>to have a small amount of jitter;<br>instead, there is a lot', x=0.5, y=0.5, xref='paper', yref='paper', showarrow=False, bgcolor='white', bordercolor='#999', opacity=0.8)
new_fig.add_annotation(text='<b>for box in fig.data:<br>box.update(jitter=0.9)</b><br>We would expect this<br>to have a lot of jitter,<br>but there appears to be none', x=0.5, y=0.5, xref='paper', yref='paper', showarrow=False, bgcolor='white', bordercolor='#999', opacity=0.8)
new_fig.update_layout(showlegend=False, title='Fig.data extracted from px.strip', template='plotly_white', width=300, height=200, margin=dict(l=0, r=0, b=0, t=40), xaxis_visible=False)
add_width.layout=new_fig.layout
add_width.update_layout(title='Adding a width param to the traces')
# Remove the annotation:
add_width.layout.annotations = [new_fig.layout.annotations[0].update({'text':'<b>update_traces(width=20, jitter=1)</b><br>Giving the boxes a width<br>just shifts everything over'})]
for demo in [fig, new_fig, add_width]: demo.show(config = {'displayModeBar': False})
@Coding-with-Adam
Copy link
Contributor

Thanks for reporting this, @janeadams
We'll do more digging into the matter and get back to you.

@archmoj

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants