我希望使用plotly重新创建张量板中可用的多直方图可视化:
各个直方图的绘制很简单,但我不知道如何对痕迹进行 3D 偏移。
我想我正在寻找一种在 3d 空间上堆叠 2d 轨迹(直方图)的方法,例如:
从那里我认为造型/透明度/相机位置的组合将使我完成剩下的工作。
我查看了
plotly
(https://plotly.com/python/3d-charts/)中的3d图,但没有找到合适的解决方案。
结束可能是https://plotly.com/python/3d-surface-plots/。
注意 5 年前的这个问题非常相似,但没有答案:如何在 Python 中使用 Plotly 绘制这种 3D 轴?
我通过调整找到了解决方案:https://community.plotly.com/t/adding-a-shape-to-a-3d-plot/1441/8
我在这里分享它,作为遇到此问题的其他人的起点:
# Note that I'm using polars dataframes, but it's trivial to convert to pandas
import numpy as np
import pandas as pd
import plotly.graph_objects as go
df = pd.DataFrame(np.random.normal(50, 5, size=(30000, 4)), columns=list('ABCD')).pipe(pl.from_pandas)
def plot_stacked_histograms(df:pl.DataFrame, columns=None, bins=None):
fig = go.Figure()
if bins is None:
bins = len(df)//20+1 # Heuristic - please select a more appropriate value if you have one
if columns is None:
columns = df.columns
def triangulate_histogram(x:list[float], y:list[float], z:list[float]):
if len(x) != len(y) != len(z) :
raise ValueError("The lists x, y, z, must have the same length")
n = len(x)
if n % 2 :
raise ValueError("The length of lists x, y, z must be an even number")
import numpy as np
pts3d = np.vstack((x, y, z)).T
pts3dp = np.array([[x[2*k+1], y[2*k+1], 0] for k in range(1, n//2-1)])
pts3d = np.vstack((pts3d, pts3dp))
#triangulate the histogram bars:
tri = [[0,1,2], [0,2,n]]
for k, i in zip(list(range(n, n-3+n//2)), list(range(3, n-4, 2))):
tri.extend([[k, i, i+1], [k, i+1, k+1]])
tri.extend([[n-3+n//2, n-3, n-2], [n-3+n//2, n-2, n-1]])
return pts3d, np.array(tri)
def column_values_to_plottable_surface(column:np.array, traceId:int, color:int):
a0=np.histogram(column, bins=bins, density=False)[0].tolist()
a0=np.repeat(a0,2).tolist()
a0.insert(0,0)
a0.pop()
a0[-1]=0
a1=np.histogram(column, bins=bins-1, density=False)[1].tolist()
a1=np.repeat(a1,2)
verts, tri = triangulate_histogram([traceId]*len(a0), a1, a0)
x, y, z = verts.T
I, J, K = tri.T
trace = go.Mesh3d(x=x, y=y, z=z, i=I, j=J, k=K, color=color, opacity=0.7)
return trace
for traceId, column in enumerate(df.select(columns).to_numpy().T):
trace = column_values_to_plottable_surface(column, traceId=traceId, color=traceId)
fig.add_traces(trace)
scene_kwargs = dict(
camera = dict(up=dict(x=0,y=1,z=2),eye=dict(x=2,y=2,z=1,)),
aspectratio = dict(x=1, y=3, z=1),
aspectmode = 'manual'
)
fig.update_layout(width=1700, height=700, scene_camera_eye_z=0.8, scene=scene_kwargs)
return fig
plot_stacked_histograms(df, bins=500)