10
votes

i worked on a simple 3d bar chart using the following code:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

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

ax.set_xlabel("x")
ax.set_ylabel("y") 
ax.set_zlabel("z")
ax.set_xlim3d(0,10)
ax.set_ylim3d(0,10) 
ax.set_zlim3d(0,2)

xpos = [2,5,8,2,5,8,2,5,8]
ypos = [1,1,1,5,5,5,9,9,9]
zpos = np.zeros(9)

dx = np.ones(9)
dy = np.ones(9)
dz = np.ones(9)

ax.bar3d(xpos, ypos, zpos, dx, dy, dz)
plt.gca().invert_xaxis()
plt.show()

Thinking of this just as a test, all seems to be clear so far. I just wondered how i can plot each of these 9 bars in a stacked way, so that e.g. each bar is divided in 4 parts that make up the whole bar.

Basically, im thinking of doing this in the way of the example here.

But instead of 2 stacks, i want to have 4. Any ideas how to proceed from the point i am now? Each hint would be so much appreciated.

Thanks!

edit: if i want to implement given values for each stacked bar, e.g:

...
z = [np.array([ 0.2, 0.6, 0.3, 0.6, 0.4, 0.3, 0.8, 0.5,  0.7]), 
     np.array([ 0.8, 0.4, 0.5, 0.2, 0.8, 0.7, 0.4, 0.2,  0.9]),
     np.array([ 0.1, 0.2, 0.4, 0.4, 0.2, 0.6, 0.3, 0.6,  0.9]),
     np.array([ 0.9, 0.5, 0.7, 0.2, 0.5, 0.6, 0.7, 0.9,  0.7])]
dz = [z for i in range(4)]
...

this doesnt seem to work and i dont know why?

1
I did something similar here, but you will probably run into difficulties with matplotlib's way of plotting depth information. My answer should be applicable to your problem though, only you have to change the zpos rather than the color/opacity of the bar plots. - Andras Deak

1 Answers

12
votes

To make a stacked 3d bar plot, you can accumulate your dz values and use them as the base for each next bar. Here's an example:

enter image description here

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

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

ax.set_xlabel("x")
ax.set_ylabel("y") 
ax.set_zlabel("z")
ax.set_xlim3d(0,10)
ax.set_ylim3d(0,10) 

xpos = [2,5,8,2,5,8,2,5,8]
ypos = [1,1,1,5,5,5,9,9,9]
zpos = np.zeros(9)

dx = np.ones(9)
dy = np.ones(9)
dz = [np.random.random(9) for i in range(4)]  # the heights of the 4 bar sets

_zpos = zpos   # the starting zpos for each bar
colors = ['r', 'b', 'g', 'y']
for i in range(4):
    ax.bar3d(xpos, ypos, _zpos, dx, dy, dz[i], color=colors[i])
    _zpos += dz[i]    # add the height of each bar to know where to start the next

plt.gca().invert_xaxis()
plt.show()