Plotly:如何制作3D堆积直方图?

4

我有几个直方图,我成功使用plotly绘制了它们,如下所示:

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

我想创建类似于这个三维堆积直方图,但是每个内部的二维直方图都应该是一个真正的直方图,而不是硬编码的线条(我的数据形式为[0.5 0.4 0.5 0.7 0.4],因此直接使用Histogram非常方便)。
请注意,我询问的内容与这个例子不同,也不同于这个例子。在matplotlib的例子中,数据直接呈现为二维数组,因此直方图是第三个维度。而在我的情况下,我想要通过向函数提供许多已经计算好的直方图来实现。
2个回答

4
下面的代码片段处理了分组和格式化图表,使其以多个go.Scatter3Dnp.Histogram的轨迹呈现为堆叠的三维图表。 输入是一个使用np.random.normal(50, 5, size=(300, 4))生成的随机数数据框。 图1:角度1 enter image description here 图2:角度2 enter image description here 完整代码:
# 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()

这看起来非常不错!如果它确实有效,我将在今天下午将其调整到我的代码中并标记为解决方案。谢谢! - J Agustin Barrachina
@AgustinBarrachina 很高兴能帮忙!我知道 a0=np.repeat(a0,2).tolist()a0.pop() 可能看起来有点奇怪。但这只是为了创建必要的数据结构,以弥补 go.Scatter3Dgo.Scatter 不同之处,即 没有 可以设置为 'hvh'line_shape 方法。在这里可以看到如何使用它来构建与您的第一个链接相同的图表。 - vestland
不错!运行得很好。然而,我尝试使用surfaceaxis=0作为go.Scatter3d的参数来使它更漂亮,但结果却很糟糕。你知道是否有可能让它正常工作吗?也许由于这是一个不同的问题,我应该提出一个新的问题... - J Agustin Barrachina
1
@AgustinBarrachina 请将其作为新问题发布。我在下周之前没有机会查看它。所以我相信其他人会在我之前接手。如果没有,我会尽快查看。 - vestland
1
这里是解决方案:https://stackoverflow.com/a/60487237/5931672 - J Agustin Barrachina

1

很遗憾,在3D空间中无法使用go.Histogram,因此您应该使用另一种方式。我使用了go.Scatter3d,并希望使用填充线选项doc,但存在明显的错误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


这里是填充曲面的解决方案。 - J Agustin Barrachina
@Augustin 不错。你或者empet可以考虑提交一个PR。 - rpanai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接