2013-07-29 127 views
2

Matplotlib可以绘制一个如下所示的堆叠柱状图吗?如果它只有一个酒吧呢?在matplotlib中创建一个堆叠的柱状图plot

如果不是,另一个选项将只是一个通常的堆叠酒吧情节与酒吧有圆边 - 这是可能的吗?

我搜索了matplotlib库和bar()文档,但找不到要做的事情。

enter image description here

回答

5

我不知道一个直接的函数来绘制堆叠的圆柱体柱状图中,我不认为有一个简单的解决办法要么。问题在于它既不是2D或3D。

使用Matplotlib,您必须使2D看起来像3D。这意味着你必须做一个圆柱体形状。为了使它看起来很好,你可能还需要一个纹理来给出阴影的外观。

mplot3d是Matplotlib的3D扩展,我用它来制作下面的图。我认为它也有点 3D。顶部看起来有点扭曲,整个剧情是在一个角度... mplot3d也是一个痛苦的工作。它需要很多努力才能使气缸看起来不错。代码不是很精美,但我确实注释了它。

Stacked cylinder bar plot with 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() 
+0

这确实令人印象深刻的工作!可能对我的应用程序太麻烦了,但是很佩服这种努力。 – TheCodeNovice