【问题标题】:Creating a stacked cylinder bar plot in matplotlib在 matplotlib 中创建堆叠柱面图
【发布时间】:2013-07-31 22:06:21
【问题描述】:

matplotlib 可以像下面这样绘制一个堆积柱面图吗?如果它只有一根呢?

如果不是,另一种选择是通常的堆叠条形图,条形边缘具有圆角 - 这可能吗?

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

【问题讨论】:

    标签: python matplotlib plot


    【解决方案1】:

    我不知道绘制堆叠圆柱条图的直接函数,我认为也没有简单的解决方法。问题是它既不是真正的 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() 
    

    【讨论】:

    • 这真是令人印象深刻的作品!!!可能对我的申请来说太麻烦了,但很佩服这种努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-28
    相关资源
    最近更新 更多