# Marginal distribution plots without express?

**URL:** <https://community.plotly.com/t/marginal-distribution-plots-without-express/83023>\
**Category:** 📊 Plotly Python\
**Tags:** question\
**Created:** [March 14, 2024, 10:47am UTC](https://community.plotly.com/t/marginal-distribution-plots-without-express/83023 "2024-03-14T10:47:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![hmijail](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@hmijail](https://community.plotly.com/u/hmijail)\
**Post date:** [March 14, 2024, 10:47am UTC](https://community.plotly.com/t/marginal-distribution-plots-without-express/83023/1 "2024-03-14T10:47:17Z")

</div>

Hi all,

I am creating multi-trace histograms one bar trace at a time because I need control that plotly.express’ histograms don’t give me (like changing traces’ visibility depending on values per bin).

However now I can’t find a way to add marginal distribution plots to my histogram. Looks like it’s a plotly.express-only thing!

Is that right? Hopefully I’m missing something…

---

<div class="post-metadata">

**Author:** ![AIMPED](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/aimped/32/21758_2.png) [@AIMPED](https://community.plotly.com/u/AIMPED)\
**Post date:** [March 14, 2024, 10:53am UTC](https://community.plotly.com/t/marginal-distribution-plots-without-express/83023/2 "2024-03-14T10:53:32Z")

</div>

Hey @hmijail welcome to the community.

Would you mind creating a minimal example for that? Are you using plotly.graph\_objects to generate your figure?

I guess you are referring to this:

> **[Marginal](https://plotly.com/python/marginal-plots/)**
>
> Over 8 examples of Marginal Distribution Plots including changing color, size, log axes, and more in Python.

---

<div class="post-metadata">

**Author:** ![hmijail](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@hmijail](https://community.plotly.com/u/hmijail)\
**Post date:** [March 14, 2024, 11:15am UTC](https://community.plotly.com/t/marginal-distribution-plots-without-express/83023/3 "2024-03-14T11:15:06Z")

</div>

Sorry, creating an example of … what? the thing that can’t be done? 😅

What I am doing is basically this:

```auto
fig = go.Figure()
bins = ...

for l in mydata:
  visibility = ...
  fig.add_bar(
        x=bins,
        y=l,
        visible=visibility,
    )
fig.show()

```

I don’t see any Figure.add\_\* mentioning marginals, so that’s where I’m blocked.

---

<div class="post-metadata">

**Author:** ![hmijail](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@hmijail](https://community.plotly.com/u/hmijail)\
**Post date:** [March 14, 2024, 11:30am UTC](https://community.plotly.com/t/marginal-distribution-plots-without-express/83023/4 "2024-03-14T11:30:44Z")

</div>

… and yes, as you see I’m using Figure from plotly.graph\_objects.

While all the examples in the link you posted use plotly.express.

---

<div class="post-metadata">

**Author:** ![AIMPED](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/aimped/32/21758_2.png) [@AIMPED](https://community.plotly.com/u/AIMPED)\
**Post date:** [March 14, 2024, 12:05pm UTC](https://community.plotly.com/t/marginal-distribution-plots-without-express/83023/5 "2024-03-14T12:05:32Z")

</div>

**TL;DR** You can re-create any figure created with `px` using `go`, it takes some effort, though

Some explanation:

As far as I know, figures created by `plotly.express` can be created by `plotly.graph_objects` as express uses graph\_objects under the hood. You might see express as a more user- friendly version of graph\_objects which does grouping with pandas or creating subplots for you.

That said, there is no function which adds marginals because they are just traces arranged in subplots.

To get an idea of what I’m referring to, just take this example:

```python
import plotly.express as px
df = px.data.iris()
fig = px.histogram(df, x="sepal_length", color="species", marginal="box", height=700)
fig.show()

```

if you convert the figure into a dictionary and print the content, you’ll find the traces which have been created by px for you.

```python
f = fig.to_dict()
print(f['data'])

```

Output:

```json
[{'alignmentgroup': 'True',
  'bingroup': 'x',
  'hovertemplate': 'species=setosa<br>sepal_length=%{x}<br>count=%{y}<extra></extra>',
  'legendgroup': 'setosa',
  'marker': {'color': '#636efa', 'pattern': {'shape': ''}},
  'name': 'setosa',
  'offsetgroup': 'setosa',
  'orientation': 'v',
  'showlegend': True,
  'x': array([5.1, 4.9, 4.7, 4.6, 5. , 5.4, 4.6, 5. , 4.4, 4.9, 5.4, 4.8, 4.8,
         4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5. ,
         5. , 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5. , 5.5, 4.9, 4.4,
         5.1, 5. , 4.5, 4.4, 5. , 5.1, 4.8, 5.1, 4.6, 5.3, 5. ]),
  'xaxis': 'x',
  'yaxis': 'y',
  'type': 'histogram'},
 {'alignmentgroup': 'True',
  'hovertemplate': 'species=setosa<br>sepal_length=%{x}<extra></extra>',
  'legendgroup': 'setosa',
  'marker': {'color': '#636efa'},
  'name': 'setosa',
  'notched': True,
  'offsetgroup': 'setosa',
  'showlegend': False,
  'x': array([5.1, 4.9, 4.7, 4.6, 5. , 5.4, 4.6, 5. , 4.4, 4.9, 5.4, 4.8, 4.8,
         4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5. ,
         5. , 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5. , 5.5, 4.9, 4.4,
         5.1, 5. , 4.5, 4.4, 5. , 5.1, 4.8, 5.1, 4.6, 5.3, 5. ]),
  'xaxis': 'x2',
  'yaxis': 'y2',
  'type': 'box'},
 {'alignmentgroup': 'True',
  'bingroup': 'x',
  'hovertemplate': 'species=versicolor<br>sepal_length=%{x}<br>count=%{y}<extra></extra>',
  'legendgroup': 'versicolor',
  'marker': {'color': '#EF553B', 'pattern': {'shape': ''}},
  'name': 'versicolor',
  'offsetgroup': 'versicolor',
  'orientation': 'v',
  'showlegend': True,
  'x': array([7. , 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5. , 5.9, 6. ,
         6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6,
         6.8, 6.7, 6. , 5.7, 5.5, 5.5, 5.8, 6. , 5.4, 6. , 6.7, 6.3, 5.6,
         5.5, 5.5, 6.1, 5.8, 5. , 5.6, 5.7, 5.7, 6.2, 5.1, 5.7]),
  'xaxis': 'x',
  'yaxis': 'y',
  'type': 'histogram'},
 {'alignmentgroup': 'True',
  'hovertemplate': 'species=versicolor<br>sepal_length=%{x}<extra></extra>',
  'legendgroup': 'versicolor',
  'marker': {'color': '#EF553B'},
  'name': 'versicolor',
  'notched': True,
  'offsetgroup': 'versicolor',
  'showlegend': False,
  'x': array([7. , 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5. , 5.9, 6. ,
         6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6,
         6.8, 6.7, 6. , 5.7, 5.5, 5.5, 5.8, 6. , 5.4, 6. , 6.7, 6.3, 5.6,
         5.5, 5.5, 6.1, 5.8, 5. , 5.6, 5.7, 5.7, 6.2, 5.1, 5.7]),
  'xaxis': 'x2',
  'yaxis': 'y2',
  'type': 'box'},
 {'alignmentgroup': 'True',
  'bingroup': 'x',
  'hovertemplate': 'species=virginica<br>sepal_length=%{x}<br>count=%{y}<extra></extra>',
  'legendgroup': 'virginica',
  'marker': {'color': '#00cc96', 'pattern': {'shape': ''}},
  'name': 'virginica',
  'offsetgroup': 'virginica',
  'orientation': 'v',
  'showlegend': True,
  'x': array([6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8,
         5.7, 5.8, 6.4, 6.5, 7.7, 7.7, 6. , 6.9, 5.6, 7.7, 6.3, 6.7, 7.2,
         6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4, 6. ,
         6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9]),
  'xaxis': 'x',
  'yaxis': 'y',
  'type': 'histogram'},
 {'alignmentgroup': 'True',
  'hovertemplate': 'species=virginica<br>sepal_length=%{x}<extra></extra>',
  'legendgroup': 'virginica',
  'marker': {'color': '#00cc96'},
  'name': 'virginica',
  'notched': True,
  'offsetgroup': 'virginica',
  'showlegend': False,
  'x': array([6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8,
         5.7, 5.8, 6.4, 6.5, 7.7, 7.7, 6. , 6.9, 5.6, 7.7, 6.3, 6.7, 7.2,
         6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4, 6. ,
         6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9]),
  'xaxis': 'x2',
  'yaxis': 'y2',
  'type': 'box'}]

```

---

<div class="post-metadata">

**Author:** ![hmijail](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@hmijail](https://community.plotly.com/u/hmijail)\
**Post date:** [March 15, 2024, 2:05am UTC](https://community.plotly.com/t/marginal-distribution-plots-without-express/83023/6 "2024-03-15T02:05:09Z")

</div>

Aha, that’s interesting… looks like I can also use fig.update\_\*() to change parts of the dictionary - or feed it to a blank figure to recreate it piecewise.

I’ll see what balance I can find between fast-but-hacky vs reliable. Thank you!
