3

I am trying to generate a box plot using subsets of a larger data set. When I show the plot, there are strange gaps in the data. is there a way to center each plot over the correct label. Also, can I remove the redundant labels in the legend?

fig = go.Figure()
melted_data = melted_data.sort_values(['model', 'alpha'])
for model, alpha in zip(combos['model'].to_list(), combos['alpha'].to_list()):
    data = melted_data[(melted_data.model == model) & (melted_data.alpha == alpha)]
    fig.add_trace(go.Box(
            y= data['value'],
            x = data['model'],
            marker_color=colors[alpha],
            name = alpha,
            boxmean=True,
        ))
fig.update_layout(
    showlegend=True,
    boxmode='group', # group together boxes of the different traces for each value of x
    boxgap = .1)
fig.show()

enter image description here

UPDATE

Here is code to reproduce the issue:

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly



colors = {'A':plotly.colors.qualitative.Plotly[0], 
          'B':plotly.colors.qualitative.Plotly[1], 
          'C':plotly.colors.qualitative.Plotly[2],
          'D':plotly.colors.qualitative.Plotly[3],
          'E':plotly.colors.qualitative.Plotly[4],}

models = ['modelA', 'modelA', 'modelA', 'modelA', 'modelA', 'modelB', 'modelB', 'modelC', 'modelC', 'modelB', ]
samples = ['A', 'B', 'C', 'D', 'E', 'A', 'B', 'B', 'D', 'C']
score_cols = ['score_{}'.format(x) for x in range(10)]
scores = [(np.random.normal(mu, sd, 10).tolist()) for mu, sd in zip((np.random.normal(.90, .06, 10)), [.06]*10)]
data = dict(zip(score_cols, scores))
data['model'] = models
data['sample'] = samples
df = pd.DataFrame(data)
melted_data = pd.melt(df, id_vars =['model', 'sample'], value_vars=score_cols)

fig = go.Figure()
for model, sample in zip(models, samples):
    data = melted_data[(melted_data['model'] == model) & (melted_data['sample'] == sample)]
    fig.add_trace(go.Box(
            y= data['value'],
            x = data['model'],
            marker_color=colors[sample],
            name = sample,
            boxmean=True,
        ))
fig.update_layout(
    showlegend=True,
    boxmode='group', # group together boxes of the different traces for each value of x
    boxgap = .1)
fig.show() 
2
  • Have you tried setting the xaxis type as category, by adding {'type': 'category'} to the xaxis layout? Docs here Commented Sep 17, 2020 at 12:59
  • 1
    Please update the question to add a sample of the data; as this example is currently not reproducible. Thanks. Commented Sep 17, 2020 at 13:24

1 Answer 1

1

I couldn't quite figure out why your go.Figure turns out the way it does. But if you reshape your data from wide to long and unleash px.bar you'll get a shorter, cleaner code and arguably a much better visual result. We can talk more details later, but you'll find a complete snippet right after this plot:

enter image description here

Complete code:

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly
import plotly.express as px



colors = {'A':plotly.colors.qualitative.Plotly[0], 
          'B':plotly.colors.qualitative.Plotly[1], 
          'C':plotly.colors.qualitative.Plotly[2],
          'D':plotly.colors.qualitative.Plotly[3],
          'E':plotly.colors.qualitative.Plotly[4],}

models = ['modelA', 'modelA', 'modelA', 'modelA', 'modelA', 'modelB', 'modelB', 'modelC', 'modelC', 'modelB', ]
samples = ['A', 'B', 'C', 'D', 'E', 'A', 'B', 'B', 'D', 'C']
score_cols = ['score_{}'.format(x) for x in range(10)]
scores = [(np.random.normal(mu, sd, 10).tolist()) for mu, sd in zip((np.random.normal(.90, .06, 10)), [.06]*10)]
data = dict(zip(score_cols, scores))
data['model'] = models
data['sample'] = samples

df = pd.DataFrame(data)

df_long = pd.wide_to_long(df, stubnames='score',
                          i=['model', 'sample'], j='type',
                          sep='_', suffix='\w+').reset_index()
df_long

fig = px.box(df_long, x='model', y="score", color ='sample')
fig.show()
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this worked out fine, it's not perfect, but I think that it will suffice. Thanks again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.