簡體   English   中英

在matplotlib中創建堆疊的圓柱條形圖

[英]Creating a stacked cylinder bar plot in matplotlib

matplotlib可以像下面的圖一樣繪制堆積的圓柱圖嗎? 如果只有一個酒吧怎么辦?

如果沒有,另一種選擇將是通常的堆疊條形圖,條形具有圓角邊緣-可能嗎?

我搜索了matplotlib畫廊和bar()文檔,但找不到要執行的操作。

在此處輸入圖片說明

我不知道直接函數來繪制堆積的圓柱條形圖,我也不認為有任何簡單的解決方法。 問題在於它既不是真正的2D也不是3D。

使用Matplotlib,您必須使2D看起來像3D。 這意味着您必須制作圓柱形狀。 為了使它看起來不錯,您可能還需要一個紋理以賦予陰影外觀。

mplot3d是Matplotlib的3D擴展,我用它來制作下面的圖。 我認為它看起來有點 3D。 頂部看起來有點變形,整個情節有一個角度……mplot3d的使用也有些痛苦。 要花費大量時間才能使圓柱體看起來不錯。 該代碼不是很完善,但我確實對其進行了注釋。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM