matplotlib可以绘制如下图所示的堆叠圆柱条图吗?如果只有一个酒吧怎么样?
如果没有,另一种选择就是通常的堆积条形图,条形边缘有圆角 - 这可能吗?
我搜索了matplotlib图库和bar()
文档,但无法找到要做的事情。
答案 0 :(得分:6)
我不知道绘制叠加柱面图的直接功能,我认为也没有一个简单的解决方法。问题是它既不是2D也不是3D。
使用Matplotlib,您必须使2D看起来像3D。这意味着您必须制作圆柱形状。为了使它看起来很好,你可能还需要一个纹理来给出阴影的外观。
mplot3d是Matplotlib的3D扩展,我用它来制作下图。我认为它看起来有点太 3D。顶部看起来有点扭曲,整个情节是一个角度...... mplot3d也有点痛苦。要使气缸看起来不错,需要花费一些力气。代码不是很精致,但我做了注释。
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from mpl_toolkits.mplot3d import Axes3D
import numpy
import matplotlib
import matplotlib.pyplot as plt
def plot_cylinder_element(x, z, dz, rx = 5, ry = 5, color = "b"):
"""
x: left, right
z: start height
dz: height of cylinder
rx, ry = radius of width (x) and depth (y)
color = color
Inspired by:
http://matplotlib.1069221.n5.nabble.com/plot-surface-shading-and-clipping-error-td14031.html
"""
N = 100 # number of elements
# a lower stride will give more faces. A cylinder with 4 faces is a cube :)
# I think with N=100 and rstride=2, it will have 50 faces
# cstride is the height, rstride the circle
cstride_side = 1000 # only 1 element needed
rstride_side = 1 # many elements to make a nice cylinder shape
cstride_top = 10
rstride_top = 10
# parameters of cylinder
phi = numpy.linspace(0, 2 * numpy.pi, N)
_r = numpy.ones(N)
_h = numpy.linspace(0, 1, N)
# cylinder
_x = rx * numpy.outer(numpy.cos(phi), _r) + x
_y = ry * numpy.outer(numpy.sin(phi), _r)
_z = dz * numpy.outer(numpy.ones(numpy.size(_r)), _h) + z
ax.plot_surface(_x, _y, _z, rstride = rstride_side, cstride = cstride_side, linewidth = 0, alpha = 1, color = color)
# to cover the gaps between the faces, plot the cylinder again at a slightly smaller radius
_x *= 0.99
_y *= 0.99
ax.plot_surface(_x, _y, _z, rstride = rstride_side + 1, cstride = cstride_side + 1, linewidth=0, alpha=1, color = color)
# top
_x = rx * numpy.outer(numpy.cos(phi), _h) + x
_y = ry * numpy.outer(numpy.sin(phi), _h)
_z = numpy.zeros([N,N]) + z + dz + 0.1
ax.plot_surface(_x, _y, _z, rstride = rstride_top, cstride = cstride_top, linewidth = 0, alpha = 1, color = color)
# plot again with different stride to mask the gaps
ax.plot_surface(_x, _y, _z, rstride = rstride_side + 1, cstride = cstride_side + 1, linewidth=0, alpha=1, color = color)
def plot_cylinder(x, z, rx = 5, ry = 5):
"""
x: left-right for each cylinder
z: list height difference (ie. not cumulative)
"""
# list with colors
colors = ["b", "g", "r", "c", "y", "k"]
# plot cylinder elements
_z = 0
for i in range(len(z)):
plot_cylinder_element(x, _z, z[i], rx = rx, ry = ry, color = colors[i % len(colors)])
_z += z[i]
def cylinder_plot(z, r = 10, dr = 30):
"""
z: list of different cylinders with for each a list height difference (ie. not cumulative)
r: radius
dr: distance between cylinders
"""
# different cylinders next to each other
x = numpy.arange(len(z)) * dr
# possible difference between width (x) and depth (y)
rx = r
ry = r
# make cylinders
for i in range(len(z)):
plot_cylinder(x[i], z[i], rx = rx, ry = ry)
# close earlier plots
plt.close("all")
# make figure
fig = plt.figure()
ax = Axes3D(fig)
# set 3D-view
ax.view_init(elev = 10, azim = 280)
# make 3 cylinders, with a different number of elements
cylinder_plot([[5, 10, 5], [3, 5], [1,2,3,4]])
# set the labels
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# show
plt.show()