2013-09-27 105 views
15

我需要一些幫助,使用matlibplot在python中製作一組堆積條形圖。我的基本代碼如下,但我的問題是如何生成底部的值超過第二個高效。我能得到的示例圖表,以確保正確堆疊(總是A,B,C,從底部d頂部)更高效matplotlib堆積條形圖 - 如何計算底部值

import numpy as np 
import matplotlib.pyplot as plt 

ind = np.arange(3) 

a = [3,6,9] 
b = [2,7,1] 
c = [0,3,1] 
d = [4,0,3] 

p1 = plt.bar(ind, a, 1, color='#ff3333') 
p2 = plt.bar(ind, b, 1, color='#33ff33', bottom=a) 
p3 = plt.bar(ind, c, 1, color='#3333ff', bottom=[a[j] +b[j] for j in range(len(a))]) 
p4 = plt.bar(ind, d, 1, color='#33ffff', bottom=[a[j] +b[j] +c[j] for j in range(len(a))]) 

plt.show() 

我的最終代碼可能有非常多的酒吧和不斷擴大的功能底部= [.. 。]不能是最好的解決方案。如果你能解釋我需要如何推導價值,那將是非常好的。是否有一個numpy功能。

非常感謝! PS我已經搜索了一個答案,但我不明白我能找到什麼。

回答

28

我剛剛面臨同樣的問題。之後,我決定將它們全部包裝在一個不錯的課堂上。對於任何有興趣的你在這裏堆積條形圖類的實現:

https://github.com/minillinim/stackedBarGraph

它允許縮放堆疊圖表以及設置欄寬度和高度設置(帶有刻度的內部件)。

如果有一個數據集是這樣的:

d = np.array([[101.,0.,0.,0.,0.,0.,0.], 
        [92.,3.,0.,4.,5.,6.,0.], 
        [56.,7.,8.,9.,23.,4.,5.], 
        [81.,2.,4.,5.,32.,33.,4.], 
        [0.,45.,2.,3.,45.,67.,8.], 
        [99.,5.,0.,0.,0.,43.,56.]]) 

    d_heights = [1.,2.,3.,4.,5.,6.] 
    d_widths = [.5,1.,3.,2.,1.,2.] 
    d_labels = ["fred","julie","sam","peter","rob","baz"] 
    d_colors = ['#2166ac', 
       '#fee090', 
       '#fdbb84', 
       '#fc8d59', 
       '#e34a33', 
       '#b30000', 
       '#777777'] 

它可以使圖片是這樣的:

stacked bar graph

GPLv3的愛。

+0

謝謝 - 我怎麼能得到酒吧之間的空間? – Matt

+0

我更新了代碼以允許差距。這實際上很簡單,如果你從條的寬度中扣除一個固定的數量,那麼它就會有效地縮小它們。之後,這只是玩xlims的問題。主函數調用現在有兩個新的參數,gap和endGaps,底部的兩個圖片顯示了這些使用中的示例。 – minillinim

+0

愛@minillinim的包。這感覺太簡單了。要添加圖例,如果您使用'stacked_colors = ['#2166ac','#fee090','#fdbb84']'和'cols = stacked_colors'等數組設置顏色,則很容易將圖例添加到從一個數據幀大熊貓作出的曲線圖: '圖例= [] I = 0 用於df.columns柱: legends.append(mpatches.Patch(顏色= stacked_colors [I],標記=列)) I + = 1 plt.legend(句柄=圖例) ' –

5
[sum(values) for values in zip(a, b, c)] 

在Python 2,你也可以做

map(sum, zip(a, b, c)) 

但是Python 3需要

list(map(sum, zip(a, b, c))) 

這是不太好的。


您可以封裝此:

def sumzip(*items): 
    return [sum(values) for values in zip(*items)] 

,然後做

p1 = plt.bar(ind, a, 1, color='#ff3333') 
p2 = plt.bar(ind, b, 1, color='#33ff33', bottom=sumzip(a)) 
p3 = plt.bar(ind, c, 1, color='#3333ff', bottom=sumzip(a, b)) 
p4 = plt.bar(ind, d, 1, color='#33ffff', bottom=sumzip(a, b, c)) 

了。


如果abcd是numpy的數組,你也可以做sum([a, b, c])

a = np.array([3,6,9]) 
b = np.array([2,7,1]) 
c = np.array([0,3,1]) 
d = np.array([4,0,3]) 

p1 = plt.bar(ind, a, 1, color='#ff3333') 
p2 = plt.bar(ind, b, 1, color='#33ff33', bottom=sum([a])) 
p3 = plt.bar(ind, c, 1, color='#3333ff', bottom=sum([a, b])) 
p4 = plt.bar(ind, d, 1, color='#33ffff', bottom=sum([a, b, c])) 
14

轉換你的價值觀,以numpy的陣列將讓您的生活更輕鬆:

data = np.array([a, b, c, d]) 
bottom = np.cumsum(data, axis=0) 
colors = ('#ff3333', '#33ff33', '#3333ff', '#33ffff') 

plt.bar(ind, data[0], color=colors[0]) 
for j in xrange(1, data.shape[0]): 
    plt.bar(ind, data[1], color=colors[j], bottom=bottom[i-1]) 

另外,爲了擺脫第一個酒吧的骯髒的特殊情況:

data = np.array([a, b, c, d]) 
bottom = np.vstack((np.zeros((data.shape[1],), dtype=data.dtype), 
        np.cumsum(data, axis=0)[:-1])) 
colors = ('#ff3333', '#33ff33', '#3333ff', '#33ffff') 
for dat, col, bot in zip(data, colors, bottom): 
    plt.bar(ind, dat, color=col, bottom=bot) 
+4

如果您使用的是matplotlib,則所有內容都會以_anyway_下的ndarray結尾。不妨讓你的生活愉快吧:) – tacaswell

+0

謝謝,我該如何添加標籤? 我有一個標籤/名稱列表,我正在堆疊的每一個系列,但儘管我已經嘗試過,但我無法讓他們出來正確。 我也嘗試運行一個簡單的圖例,如下所示,但它並沒有真正的工作。: 'code'plt.legend((pl [0],pm [0],ph [0],pa [0]) ,('L','M','H','At'),bbox_to_anchor = [1.05,0.5],loc ='center') –

1

我解決了它這樣的:

import numpy as np 

dates = # somehow get a list of dates 
labels = # a list of various labels 
colors = # somehow get a list of colors 

margin_bottom = np.zeros(dates) 

for index, label in enumerate(labels): 
    values = # get your values for the label at index-th position from somewhere 
    ax.bar(
     dates, values, 
     align='center', label=label, color=colors[index], bottom=margin_bottom 
    ) 
    margin_bottom += values # here you simply add it to the previous margin 
    # margin_bottom is a numpy array, adding a list will not change that 

它類似於一些其他的解決方案,但它不要求所有的利潤被存儲在所有的時間。相反,它會從下往上「堆砌」堆棧,每次迭代都會增加更多的餘量。