如何在轴系统上创建多个 3D 圆柱图?

How to create many 3D cylindrical plots on an axis system?

python 中是否有库或方法能够创建看起来像这样的图? (为了将图表嵌入 HTML 页,最好基于 MatPlotLib)

我的目标是创建从 Neo4J 数据库读取的数据的 3D 渲染并将它们建模为上面的圆柱体。

下面的代码尝试创建一个类似的 3D 图(不是圆柱形而是矩形),其中包含来自数据框的图例。情节是互动的。资源:, , 3, 4 (Jupyter Notebook 5.0.0, Python 3.6.6)

导入库

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from mpl_toolkits.mplot3d import axes3d  
import matplotlib.patches as mpatches # for legends
%matplotlib notebook

创建示例数据框

# Create two sets of identical xpos and ypos 
# So taht the z-values are plotted at same location for stacking
xtemp = np.random.randint(1, 10, size=5)
ytemp = np.random.randint(1, 10, size=5)

df = pd.DataFrame({
    # category
    'season': ['S1']*5 + ['S2']*5 + ['S3']*5,
    #'wins': np.random.randint(1, 10, size=15),
    # define pos
    'xpos' : list(xtemp)+list(xtemp)+list(xtemp),
    'ypos' : list(ytemp)+list(ytemp)+list(ytemp),
    'zpos' : np.zeros(15),
    # define delta
    'dx': 0.8*np.ones(15),
    'dy': 0.8*np.ones(15),
    'dz': np.random.randint(1, 5, size=15), #np.ones(15)

})
df.head(5)

画图

注意:图分为两部分:(1) N-S、E-W 线的 2D 图和 (2) 3D 条形图

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# ..................
# Line-1 on x-y plane
x = [4, 4]
y = [-3, 12]
ax.plot(x, y, zs=0, zdir='z', color='orange', alpha=0.8)


# Line-2 on x-y plane
y = [4, 4]
x = [-3, 12]
ax.plot(x, y, zs=0, zdir='z', color='blue', alpha=0.5)


# Creat multiple overlap plots within a loop

color = ['#6495ED', '#6E8B3D', '#FFB90F']
slist = ['S1', 'S2', 'S3']
stack_zpos = pd.Series(np.zeros(5)) 
for i in range(0,3):
    q = df[df['season']==slist[i]].reset_index(inplace=False)
    ax.bar3d(q.xpos, q.ypos, stack_zpos, q.dx, q.dy, q.dz, color=color[i], alpha=1)
    stack_zpos += q.dz  # values added here for stacking

注释线条并删除 z 轴窗格和网格线

# Remove the z-axis panes, grids and lines
alpha = 0
ax.w_xaxis.set_pane_color((1.0, 1.0, 1.0, alpha))
ax.w_yaxis.set_pane_color((1.0, 1.0, 1.0, alpha))
#
ax.zaxis._axinfo["grid"]['color'] = (1.0, 1.0, 1.0, alpha)
ax.w_yaxis._axinfo["grid"]['linewidth'] = 0
ax.w_xaxis._axinfo["grid"]['linewidth'] = 0
#
ax.w_zaxis.line.set_lw(0.)
ax.set_zticks([])
#
ax.set_zlabel("") # remove z-axis label 'z'

# ..........
# Annotate the N, S, E, W lines on the x-y plane
zdirs = (None, 'x', 'y', 'z', (1, 1, 0), (1, 1, 1))
xs = (4, 4, -3, 12)
ys = (-3,12, 4, 4)
zs = (0, 0, 0, 0)

i=0 # Counter
nsew = ['N', 'S', 'E', 'W'] # list of labels
for zdir, x, y, z in zip(zdirs, xs, ys, zs):
    label = '{0}'.format(nsew[i])
    #label = 'N, S, E, W' #% (x, y, z, zdir)
    ax.text(x, y, z, label, zdir)
    i +=1 

创建图例并向图中添加图例

# Add legend
patch1 = mpatches.Patch(color=color[0], label=slist[0])
patch2 = mpatches.Patch(color=color[1], label=slist[1])
patch3 = mpatches.Patch(color=color[2], label=slist[2])

plt.legend(handles=[patch1, patch2,patch3])

可视化绘图

plt.show()