Как сделать гистограмму из списка строк в Python?

У меня есть список строк:

a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e']

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

from itertools import groupby
b = [len(list(group)) for key, group in groupby(a)]

Как создать гистограмму? У меня может быть миллион таких элементов в списке a.

Ответы

Ответ 1

Очень легко с Pandas.

import pandas
from collections import Counter
a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e']
letter_counts = Counter(a)
df = pandas.DataFrame.from_dict(letter_counts, orient='index')
df.plot(kind='bar')

Обратите внимание, что Counter делает частоту, поэтому наш тип графика 'bar' not 'hist'.

histogram of letter counts

Ответ 2

Поскольку @notconfusing, указанный выше, можно решить с помощью Pandas и Counter. Если для по какой-либо причине вам не нужно использовать Pandas, вы можете обойтись только с помощью matplotlib с помощью функции в следующем коде:

from collections import Counter
import numpy as np
import matplotlib.pyplot as plt

a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e']
letter_counts = Counter(a)

def plot_bar_from_counter(counter, ax=None):
    """"
    This function creates a bar plot from a counter.

    :param counter: This is a counter object, a dictionary with the item as the key
     and the frequency as the value
    :param ax: an axis of matplotlib
    :return: the axis wit the object in it
    """

    if ax is None:
        fig = plt.figure()
        ax = fig.add_subplot(111)

    frequencies = counter.values()
    names = counter.keys()

    x_coordinates = np.arange(len(counter))
    ax.bar(x_coordinates, frequencies, align='center')

    ax.xaxis.set_major_locator(plt.FixedLocator(x_coordinates))
    ax.xaxis.set_major_formatter(plt.FixedFormatter(names))

    return ax

plot_bar_from_counter(letter_counts)
plt.show()

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

Ответ 3

Вместо использования groupby() (который требует сортировки вашего ввода) используйте collections.Counter(); это не должно создавать промежуточные списки только для подсчета входов:

from collections import Counter

counts = Counter(a)

Вы не указали, что вы считаете "гистограммой". Предположим, вы хотели сделать это на терминале:

width = 120  # Adjust to desired width
longest_key = max(len(key) for key in counts)
graph_width = width - longest_key - 2
widest = counts.most_common(1)[0][1]
scale = graph_width / float(widest)

for key, size in sorted(counts.items()):
    print('{}: {}'.format(key, int(size * scale) * '*'))

Демо:

>>> from collections import Counter
>>> a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e']
>>> counts = Counter(a)
>>> width = 120  # Adjust to desired width
>>> longest_key = max(len(key) for key in counts)
>>> graph_width = width - longest_key - 2
>>> widest = counts.most_common(1)[0][1]
>>> scale = graph_width / float(widest)
>>> for key, size in sorted(counts.items()):
...     print('{}: {}'.format(key, int(size * scale) * '*'))
... 
a: *********************************************************************************************
b: **********************************************
c: **********************************************************************
d: ***********************
e: *********************************************************************************************************************

Более сложные инструменты находятся в numpy.histogram() и matplotlib.pyplot.hist(). Они делают подсчет для вас, matplotlib.pyplot.hist() также предоставляет вам вывод графика.

Ответ 4

Отъезд matplotlib.pyplot.bar. Существует также numpy.histogram, который является более гибким, если вы хотите использовать более широкие бункеры.

Ответ 5

Простой и эффективный способ создания гистограммы персонажа в python

import numpy as np

import matplotlib.pyplot as plt

from collections import Counter



a = []
count =0
d = dict()
filename = raw_input("Enter file name: ")
with open(filename,'r') as f:
    for word in f:
        for letter  in word:
            if letter not in d:
                d[letter] = 1
            else:
                d[letter] +=1
num = Counter(d)
x = list(num.values())
y = list(num.keys())

x_coordinates = np.arange(len(num.keys()))
plt.bar(x_coordinates,x)
plt.xticks(x_coordinates,y)
plt.show()
print x,y

Ответ 6

здесь сжатый подход all pandas:

a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e']
pd.Series(a).value_counts().plot('bar')

barplot of counts