Интегрировать гистограмму в python?

Есть ли в matplotlib простая команда, которая позволяет мне взять интеграл гистограммы в определенном диапазоне? Если я построю гистограмму с помощью: fig = plt.hist(x, bins) Тогда есть ли такая команда, как fig.integral(bin1, bin2)? Что вернет интеграл гистограммы от bin1 до bin2?


person jam    schedule 30.04.2015    source источник
comment
Вы действительно должны предоставить минимальный пример, чтобы мы знали, какие у вас переменные. В частности, что такое bins? Если это целое число, вы можете использовать мой ответ, но если нет, вам нужно что-то более гибкое, например, то, что опубликовал cphlewis.   -  person Matthew Turner    schedule 30.04.2015
comment
hist теперь имеет ключевое слово cumulative для построения кумулятивного графика. Не уверен, нужны ли вам значения или просто сюжет.   -  person esmit    schedule 01.02.2019


Ответы (2)


Во-первых, помните, что интеграл — это просто общая площадь под кривой. В случае гистограммы интеграл (в псевдопитоне) равен sum([bin_width[i] * bin_height[i] for i in bin_indexes_to_integrate]).

В качестве справки см. этот пример использования гистограммы в matplotlib: http://matplotlib.org/1.2.1/examples/pylab_examples/histogram_demo.html.

Здесь они разделяют вывод plt.histogram на три части: n, bins и patches. Мы можем использовать это разделение для реализации «интеграла», который вы запрашиваете, вот так.

Предполагая, что bin1 и bin2 являются индексами бинов, которые вы хотите интегрировать, затем вычислите интеграл следующим образом:

# create some dummy data to make a histogram of
import numpy as np
x = np.random.randn(1000)
nbins = 10
# use _ to assign the patches to a dummy variable since we don't need them
n, bins, _ = plt.hist(x, nbins)

# get the width of each bin
bin_width = bins[1] - bins[0]
# sum over number in each bin and mult by bin width, which can be factored out
integral = bin_width * sum(n[bin1:bin2])

Если вы определили bins как список с разной шириной, вам нужно сделать что-то вроде того, что сказал @cphlewis (это работает без отключения на единицу):

integral = sum(np.diff(bins[bin1:bin2])*n[bin1:bin2]) 

Также стоит ознакомиться с документацией по API для matplotlib.pyplot.hist.

person Matthew Turner    schedule 30.04.2015
comment
Я думаю, это работает только для соседних ящиков? (особенно, поскольку они не должны быть одинаковой ширины?) - person cphlewis; 30.04.2015
comment
OP говорит, что они хотят взять интеграл из/в bin1 и bin2. Я предполагал, что bins было целым числом, но вы правы, если это список с разной шириной, это не сработает. - person Matthew Turner; 30.04.2015
comment
Мне не было ясно, что bin1 и bin2 являются смежными, как bins[1] и bins[2]`, или просто имена аргументов 1 и 2. @Jess, будьте осторожны при интегрировании по расстоянию или по неправильным бинам. - person cphlewis; 30.04.2015
comment
Мне пришлось немного изменить формулу, чтобы избежать ошибки на единицу. Это сработало для меня: integral = sum(np.diff(bins[bin1:bin2+1])*n[bin1:bin2]) - person m81; 20.02.2020

Команда plt.hist возвращает все данные, необходимые для его создания. Если out = plt.hist(...), высота бина равна out[0], а ширина бина равна diff(out[1]). Например.,

sum(out[0][4:7]*diff(out[1][4:8]))

для интеграла по бинам 4-6 включительно. diff вычисляет ширину каждого бина, поэтому он обрабатывает бины разной ширины, а умножение происходит поэлементно, поэтому вычисляет площади каждого прямоугольника на гистограмме.

person cphlewis    schedule 30.04.2015