J'ai une liste de chaînes:
a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e']
Je veux faire un histogramme pour afficher la distribution de fréquence des lettres. Je peux faire une liste contenant le nombre de chaque lettre en utilisant les codes suivants:
from itertools import groupby
b = [len(list(group)) for key, group in groupby(a)]
Comment est-ce que je fais l'histogramme? J'ai peut-être un million d'éléments de cette liste a
.
Très facile avec 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')
Notez que Counter
effectue un compte de fréquence, notre type de tracé est donc 'bar'
et non 'hist'
.
Comme @notconfusing l'a souligné ci-dessus, cela peut être résolu avec Pandas et Counter. Si, pour pour une raison quelconque, vous n’avez pas besoin d’utiliser Pandas, vous ne pourrez vous en sortir qu’avec matplotlib
en utilisant la fonction du code suivant:
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()
Plutôt que d'utiliser groupby()
(ce qui nécessite de trier vos entrées), utilisez collections.Counter()
; il n'est pas nécessaire de créer des listes intermédiaires uniquement pour compter les entrées:
from collections import Counter
counts = Counter(a)
Vous n'avez pas vraiment précisé ce que vous considérez être un "histogramme". Supposons que vous souhaitiez le faire sur le terminal:
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) * '*'))
Démo:
>>> 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: *********************************************************************************************************************
Des outils plus sophistiqués se trouvent dans les fonctions numpy.histogram()
et matplotlib.pyplot.hist()
. Ceux-ci font le décompte pour vous, avec matplotlib.pyplot.hist()
vous fournissant également une sortie graphique.
Découvrez matplotlib.pyplot.bar
. Il existe également numpy.histogram
qui est plus flexible si vous souhaitez des bacs plus larges.
Un moyen simple et efficace de créer un histogramme de caractère en 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