More efficient matplotlib stacked bar chart - how to calculate bottom values

前端 未结 4 485
悲哀的现实
悲哀的现实 2021-01-30 23:26

I need some help making a set of stacked bar charts in python with matlibplot. My basic code is below but my problems is how to generate the value for bottom fo

相关标签:
4条回答
  • 2021-01-31 00:21

    I solved it like this:

    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
    

    It's similar to some other solutions, but it doesn't require all of the margins being stored at all time. Instead it "builds" the stacks from bottom up, adding more and more margin with each iteration.

    0 讨论(0)
  • 2021-01-31 00:22
    [sum(values) for values in zip(a, b, c)]
    

    In Python 2 you can also do

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

    but Python 3 would need

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

    which is less nice.


    You could encapsulate this:

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

    and then do

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

    too.


    If a, b, c and d are numpy arrays you can also do 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]))
    
    0 讨论(0)
  • 2021-01-31 00:24

    I have just recently faced the same problem. Afterwards I decided to wrap it all up in a nice class. For anyone interested you get an implementation of a stacked bar graph class here:

    https://github.com/minillinim/stackedBarGraph

    It allows scaled stacked graphs as well as setting bar widths and set heights (with scaled inners).

    Given a data set like this:

        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']
    

    It can make images like this:

    stacked bar graph

    GPLv3 with love.

    0 讨论(0)
  • 2021-01-31 00:30

    Converting your values to numpy arrays will make your life easier:

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

    Alternatively, to get rid of the nasty particular case for the first bar:

    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)
    
    0 讨论(0)
提交回复
热议问题