Are there libraries or methods in python that are capable of creating plots that look like this? (preferably based around MatPlotLib for the sake of embedding the plots in HTML pages)
My goal is to create 3D renderings of data that is read from a Neo4J database and model them as the cylinders above.
The code below attempts to create a similar 3D plot (not cylindrical but rectangular) with legends from a dataframe. The plot is interactive. Resources: 1, 2, 3, 4 (Jupyter Notebook 5.0.0, Python 3.6.6
)
Import libraries
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 a sample dataframe
# 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)
Plot the figure
Note: Figure are in two parts: (1) 2D plot for the N-S, E-W lines and (2) 3D bar plot
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
Annotate lines and remove z-axis panes and grid lines
# 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
Create and add legends to the plot
# 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])
Visualize plot
plt.show()