Более эффективная гистограмма диаграммы matplotlib – как рассчитать нижние значения

Мне нужна помощь в создании набора диаграмм столбчатых диаграмм в python с matlibplot. Мой базовый код ниже, но мои проблемы состоят в том, как эффективно генерировать значение для дна для любого элемента за пределами второго. Я могу получить примерный граф для правильного стека (всегда a, b, c, d снизу вверх)

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

Мой последний код может иметь очень большое количество баров, и постоянно расширяющаяся функция bottom = […] не может быть лучшим решением. Было бы здорово, если бы вы также могли объяснить, как мне нужно получить ценность. Есть функция numpy.

Большое спасибо!!! PS Я искал ответ, но я не понимал, что я могу найти.

4 Solutions collect form web for “Более эффективная гистограмма диаграммы matplotlib – как рассчитать нижние значения”

Я совсем недавно столкнулся с той же проблемой. Впоследствии я решил обернуть все в класс. Для всех, кого это интересует, вы получаете реализацию класса столбчатых столбцов:

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

Он может создавать такие образы:

гистограмма

GPLv3 с любовью.

Преобразование ваших значений в массивы 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) 
 [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)) 

слишком.


Если a , b , c и d являются массивами 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])) 

Я решил это так:

 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 

Он похож на некоторые другие решения, но он не требует, чтобы все поля сохранялись в любое время. Вместо этого он «строит» стеки снизу вверх, добавляя все больше и больше полей с каждой итерацией.

 
Interesting Posts for Van-Lav
Python - лучший язык программирования в мире.