J Agustin Barrachina
J Agustin Barrachina

Reputation: 4090

Plotly: How to make a 3D stacked histogram?

I have several histograms that I succeded to plot using plotly like this:

fig.add_trace(go.Histogram(x=np.array(data[key]), name=self.labels[i]))

I would like to create something like this 3D stacked histogram but with the difference that each 2D histogram inside is a true histogram and not just a hardcoded line (my data is of the form [0.5 0.4 0.5 0.7 0.4] so using Histogram directly is very convenient)

Note that what I am asking is not similar to this and therefore also not the same as this. In the matplotlib example, the data is presented directly in a 2D array so the histogram is the 3rd dimension. In my case, I wanted to feed a function with many already computed histograms.

Upvotes: 4

Views: 4521

Answers (2)

vestland
vestland

Reputation: 61074

The snippet below takes care of both binning and formatting of the figure so that it appears as a stacked 3D chart using multiple traces of go.Scatter3D and np.Histogram. The input is a dataframe with random numbers using np.random.normal(50, 5, size=(300, 4)) We can talk more about the other details if this is something you can use:

Plot 1: Angle 1

enter image description here

Plot 2: Angle 2

enter image description here

Complete code:

# imports
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio

pio.renderers.default = 'browser'

# data
np.random.seed(123)
df = pd.DataFrame(np.random.normal(50, 5, size=(300, 4)), columns=list('ABCD'))

# plotly setup
fig=go.Figure()

# data binning and traces
for i, col in enumerate(df.columns):
    a0=np.histogram(df[col], bins=10, density=False)[0].tolist()
    a0=np.repeat(a0,2).tolist()
    a0.insert(0,0)
    a0.pop()
    a1=np.histogram(df[col], bins=10, density=False)[1].tolist()
    a1=np.repeat(a1,2)
    fig.add_traces(go.Scatter3d(x=[i]*len(a0), y=a1, z=a0,
                                mode='lines',
                                name=col
                               )
                  )
fig.show()

Upvotes: 4

rpanai
rpanai

Reputation: 13437

Unfortunately you can't use go.Histogram in a 3D space so you should use an alternative way. I used go.Scatter3d and I wanted to use the option to fill line doc but there is an evident bug see

import numpy as np
import plotly.graph_objs as go

# random mat
m = 6
n = 5
mat = np.random.uniform(size=(m,n)).round(1)

# we want to have the number repeated
mat = mat.repeat(2).reshape(m, n*2)

# and finally plot

x = np.arange(2*n)
y = np.ones(2*n)
fig = go.Figure()
for i in range(m):
    fig.add_trace(go.Scatter3d(x=x,
                               y=y*i,
                               z=mat[i,:],
                               mode="lines",
                               # surfaceaxis=1 # bug
                               )
                 )
fig.show()

enter image description here

Upvotes: 1

Related Questions