在matplotlib中创建堆叠的圆柱条形图 [英] Creating a stacked cylinder bar plot in matplotlib

查看:62
本文介绍了在matplotlib中创建堆叠的圆柱条形图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

matplotlib 可以绘制如下图所示的堆积圆柱条形图吗?如果只有一根吧怎么办?

Can matplotlib draw a stacked cylinder bar plot like the one below? How about if it has only one bar?

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

If not, another option would be just a usual stacked bar plot with the bars having rounded edges - is that possible?

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

I searched the matplotlib gallery and bar() documentation, but couldn't find something to do it.

推荐答案

我不知道直接函数来绘制堆积的圆柱条形图,我也不认为有任何简单的解决方法.问题在于它既不是真正的2D也不是3D.

I don't know of a direct function to plot a stacked cylinder bar plot and I don't think there is an easy workaround either. The problem is that it is neither really 2D or 3D.

使用 Matplotlib,您必须使 2D 看起来像 3D.这意味着您必须制作一个圆柱形状.为了让它看起来不错,你可能还需要一个纹理来提供阴影的外观.

With Matplotlib you have to make 2D look like 3D. This means you have to make a cylinder shape. To make it look good you'll probably need a texture as well to give the appearance of shadow.

mplot3d是Matplotlib的3D扩展,我用它来制作下面的图.我认为它看起来有点 3D.顶部看起来有点扭曲,整个情节成一个角度...... mplot3d 使用起来也有点痛苦.要花费很多时间才能使圆柱体看起来不错.该代码不是很完善,但我确实对其进行了注释.

mplot3d is a 3D extension of Matplotlib and I used it to make the plot below. I think it looks a bit too 3D. The top looks a bit distorted and the whole plot is at an angle... mplot3d is also a bit of a pain to work with. It takes quite some effort to make the cylinder look nice. The code is not very polished, but I did annotate it.

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() 

这篇关于在matplotlib中创建堆叠的圆柱条形图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆