Постройте полосу с помощью matplotlib, используя словарь


96

Есть ли способ построить гистограмму, matplotlibиспользуя данные непосредственно из dict?

Мой диктат выглядит так:

D = {u'Label1':26, u'Label2': 17, u'Label3':30}

я ожидал

fig = plt.figure(figsize=(5.5,3),dpi=300)
ax = fig.add_subplot(111)
bar = ax.bar(D,range(1,len(D)+1,1),0.5)

работать, но это не так.

Вот ошибка:

>>> ax.bar(D,range(1,len(D)+1,1),0.5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 4904, in bar
    self.add_patch(r)
  File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 1570, in add_patch
    self._update_patch_limits(p)
  File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 1588, in _update_patch_limits
    xys = patch.get_patch_transform().transform(vertices)
  File "/usr/local/lib/python2.7/site-packages/matplotlib/patches.py", line 580, in get_patch_transform
    self._update_patch_transform()
  File "/usr/local/lib/python2.7/site-packages/matplotlib/patches.py", line 576, in _update_patch_transform
    bbox = transforms.Bbox.from_bounds(x, y, width, height)
  File "/usr/local/lib/python2.7/site-packages/matplotlib/transforms.py", line 786, in from_bounds
    return Bbox.from_extents(x0, y0, x0 + width, y0 + height)
TypeError: coercing to Unicode: need string or buffer, float found

Можете поделиться конкретно, что не работает? У вас есть исключение? Какое исключение? Поделитесь как можно большим количеством информации.
Inbar Rose

@InbarRose извините, я обновил вопрос, указав ошибку, которую он показывает ... что-то, касающееся строки или буфера ... Я не понимаю это сообщение об ошибке.
otmezger

2
Непонятно, чего вы хотите достичь, но в ax.bar(D,range(1,len(D)+1,1),0.5)первом аргументе должен быть список чисел, в вашем случае D.values().
Адрианп

2
Однострочник для этого невозможен, по крайней мере, насколько мне известно.
Адрианп

1
Возможно, вы захотите отправить для этого запрос функции на сайт github, потому что это кажется полезным.
tacaswell

Ответы:


162

Вы можете сделать это в две строки, сначала построив гистограмму, а затем установив соответствующие отметки:

import matplotlib.pyplot as plt

D = {u'Label1':26, u'Label2': 17, u'Label3':30}

plt.bar(range(len(D)), list(D.values()), align='center')
plt.xticks(range(len(D)), list(D.keys()))
# # for python 2.x:
# plt.bar(range(len(D)), D.values(), align='center')  # python 2.x
# plt.xticks(range(len(D)), D.keys())  # in python 2.x

plt.show()

Обратите внимание, что предпоследняя строка должна читаться plt.xticks(range(len(D)), list(D.keys()))в python3, потому что D.keys()возвращает генератор, который matplotlib не может использовать напрямую.


2
вы можете, конечно, обернуть эти две строки в функцию, и тогда она станет однострочным;)
tacaswell

2
Если вы используете объекты фигур и осей, этоax.set_xticklabels
Марк

2
Благодарность! Но у меня есть некоторые эстетические проблемы с plt.xticks, не могли бы вы рассказать нам, как переместить их по вертикали из горизонтали.
moldovean

2
выровнены ли пары ключ-значение, когда dict не отсортирован?
ssm

2
Dicts Python не могут быть отсортированы. Следовательно, порядок всегда произвольный. Однако ключи и значения всегда согласованы с приведенным выше кодом.
Дэвид Цвикер


35

Для справки в будущем: приведенный выше код не работает с Python 3. Для Python 3 D.keys()необходимо преобразовать в список.

import matplotlib.pyplot as plt

D = {u'Label1':26, u'Label2': 17, u'Label3':30}

plt.bar(range(len(D)), D.values(), align='center')
plt.xticks(range(len(D)), list(D.keys()))

plt.show()

8

Лучший способ реализовать это, используя matplotlib.pyplot.bar(range, height, tick_label)где диапазон предоставляет скалярные значения для позиционирования соответствующей полосы на графике. tick_labelработает так же, как xticks(). Можно также заменить его целым числом и использовать несколько plt.bar(integer, height, tick_label). Для получения подробной информации обратитесь к документации .

import matplotlib.pyplot as plt

data = {'apple': 67, 'mango': 60, 'lichi': 58}
names = list(data.keys())
values = list(data.values())

#tick_label does the some work as plt.xticks()
plt.bar(range(len(data)),values,tick_label=names)
plt.savefig('bar.png')
plt.show()

введите описание изображения здесь

Кроме того, такой же график можно создать без использования range(). Но возникшая проблема заключалась в том, tick_labelчто сработало только последнее plt.bar()обращение. Следовательно, xticks()для маркировки использовались:

data = {'apple': 67, 'mango': 60, 'lichi': 58}
names = list(data.keys())
values = list(data.values())
plt.bar(0,values[0],tick_label=names[0])
plt.bar(1,values[1],tick_label=names[1])
plt.bar(2,values[2],tick_label=names[2])
plt.xticks(range(0,3),names)
plt.savefig('fruit.png')
plt.show()

введите описание изображения здесь


4

Я часто загружаю dict в DataFrame pandas, а затем использую функцию построения графика DataFrame.
Вот однострочный:

pandas.DataFrame(D, index=['quantity']).plot(kind='bar')

итоговый сюжет


4

Почему не просто:

import seaborn as sns

sns.barplot(list(D.keys()), list(D.values()))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.