web-dev-qa-db-fra.com

Tracer un histogramme à partir de données pré-comptées dans Matplotlib

Je voudrais utiliser Matplotlib pour tracer un histogramme sur des données qui ont été pré-comptées. Par exemple, disons que j'ai les données brutes

data = [1, 2, 2, 3, 4, 5, 5, 5, 5, 6, 10]

Compte tenu de ces données, je peux utiliser

pylab.hist(data, bins=[...])

pour tracer un histogramme.

Dans mon cas, les données ont été pré-comptées et sont représentées comme un dictionnaire:

counted_data = {1: 1, 2: 2, 3: 1, 4: 1, 5: 4, 6: 1, 10: 1}

Idéalement, j'aimerais transmettre ces données pré-comptées à une fonction d'histogramme qui me permet de contrôler les largeurs de bacs, la plage de tracé, etc., comme si je leur avais transmis les données brutes. Comme solution de contournement, j'étends mes comptes dans les données brutes:

data = list(chain.from_iterable(repeat(value, count)
            for (value, count) in counted_data.iteritems()))

C'est inefficace lorsque counted_data contient le nombre de millions de points de données.

Existe-t-il un moyen plus simple d'utiliser Matplotlib pour produire un histogramme à partir de mes données pré-comptées?

Sinon, s'il est plus facile de simplement tracer des données qui ont été pré-regroupées, existe-t-il une méthode pratique pour "cumuler" mes comptes par article en nombres regroupés?

32
Josh Rosen

J'ai utilisé pyplot.hist l'option weights pour pondérer chaque clé par sa valeur, produisant l'histogramme que je voulais:

pylab.hist(counted_data.keys(), weights=counted_data.values(), bins=range(50))

Cela me permet de compter sur hist pour regrouper mes données.

17
Josh Rosen

Vous pouvez utiliser l'argument de mot clé weights pour np.histgram (lequel plt.hist appels en dessous)

val, weight = Zip(*[(k, v) for k,v in counted_data.items()])
plt.hist(val, weights=weight)

En supposant que vous seulement ayez des entiers comme clés, vous pouvez également utiliser bar directement:

min_bin = np.min(counted_data.keys())
max_bin = np.max(counted_data.keys())

bins = np.arange(min_bin, max_bin + 1)
vals = np.zeros(max_bin - min_bin + 1)

for k,v in counted_data.items():
    vals[k - min_bin] = v

plt.bar(bins, vals, ...)

où ... correspond aux arguments que vous souhaitez transmettre à bar(doc)

Si vous souhaitez regrouper vos données, voir Histogramme avec liste séparée indiquant la fréquence

21
tacaswell

Vous pouvez également utiliser seaborn pour tracer l'histogramme:

import matplotlib.pyplot as plt
import seaborn as sns

sns.distplot(list(counted_data.keys()), hist_kws={"weights":list(counted_data.values())})
3
youssef mhiri

la longueur du tableau "bacs" doit être plus longue que la longueur des "comptes". Voici la façon de reconstruire entièrement l'histogramme:

import numpy as np
import matplotlib.pyplot as plt
bins = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]).astype(float)
counts = np.array([5, 3, 4, 5, 6, 1, 3, 7]).astype(float)
centroids = (bins[1:] + bins[:-1]) / 2
counts_, bins_, _ = plt.hist(centroids, bins=len(counts),
                             weights=counts, range=(min(bins), max(bins)))
plt.show()
assert np.allclose(bins_, bins)
assert np.allclose(counts_, counts)
2
R. Yang