Подтвердить что ты не робот

Построение гистограммы из предварительно подсчитанных данных в Matplotlib

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

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

Учитывая эти данные, я могу использовать

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

для построения гистограммы.

В моем случае данные были предварительно подсчитаны и представлены в виде словаря:

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

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

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

Это неэффективно, когда counted_data содержит подсчеты для миллионов точек данных.

Существует ли более простой способ использования Matplotlib для создания гистограммы из моих предварительно подсчитанных данных?

В качестве альтернативы, если проще всего использовать данные штрихового графика, предварительно подготовленные, есть ли удобный метод для "свертывания" моих подсчетов по каждому элементу в подсчет числа?

4b9b3361

Ответ 1

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

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

Это позволяет мне полагаться на hist для повторной загрузки моих данных.

Ответ 2

Вы можете использовать аргумент ключевого слова weights для np.histgram (который plt.hist вызывает под ним)

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

Предполагая, что у вас есть только целые числа, вы также можете напрямую использовать bar:

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, ...)

где... это то, что вы хотите передать в bar (doc)

Если вы хотите переустановить свои данные, см. Гистограмма с отдельной частотой обозначений в списке

Ответ 3

длина массива "бинов" должна быть длиннее длины "counts". Здесь можно полностью восстановить гистограмму:

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)