2013-12-04 4 views
4

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

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

enter image description here

Это MWE у меня до сих пор:

import matplotlib.pyplot as plt 
import numpy as np 
from scipy import stats 

# Generate random data uniformly distributed. 
a = np.random.normal(1., 0.1, 1000) 
b = np.random.normal(1., 0.1, 1000) 

# Obtain KDE estimates foe each set of data. 
xmin, xmax = -1., 2. 
x_pts = np.mgrid[xmin:xmax:1000j] 
# Kernels. 
ker_a = stats.gaussian_kde(a) 
ker_b = stats.gaussian_kde(b) 
# KDEs for plotting. 
kde_a = np.reshape(ker_a(x_pts).T, x_pts.shape) 
kde_b = np.reshape(ker_b(x_pts).T, x_pts.shape) 


# Random sample from a KDE distribution. 
sample = ker_a.resample(size=1000) 

# Compute the points below which to integrate. 
iso = ker_b(sample) 

# Filter the sample. 
insample = ker_a(sample) < iso 

# As per Monte Carlo, the integral is equivalent to the 
# probability of drawing a point that gets through the 
# filter. 
integral = insample.sum()/float(insample.shape[0]) 

print integral 

plt.xlim(0.4,1.9) 
plt.plot(x_pts, kde_a) 
plt.plot(x_pts, kde_b) 

plt.show() 

, где я применяю Monte Carlo для получения интеграла.

Проблема этого метода состоит в том, что, когда я оценить выборку точек в любом распределении с ker_b(sample) (или ker_a(sample)), я получаю значения размещены непосредственно над линию KDE. Из-за этого даже четко перекрывающиеся распределения, которые должны возвращать общее/перекрываемое значение области, очень близкое к 1. возвращают вместо этого небольшие значения (общая площадь любой кривой равна 1., так как они являются оценками плотности вероятности).

Как я могу исправить этот код, чтобы дать ожидаемые результаты?


Это, как я применил ответ Жени

# Calculate overlap between the two KDEs. 
def y_pts(pt): 
    y_pt = min(ker_a(pt), ker_b(pt)) 
    return y_pt 
# Store overlap value. 
overlap = quad(y_pts, -1., 2.) 
+1

http://stackoverflow.com/questions/15361125/calculate-area-between-two-curves-that-are-normal-distributions/15361352#15361352 –

+0

Я собираюсь над вашим ответом в вопросе, который вы связали, и, похоже, он применим и здесь, хотя первоначально предполагал, что он будет работать только для нормальных распределений. Не могли бы вы опубликовать свой комментарий в форме ответа? Таким образом, если он работает, я могу отметить его как принятый. Спасибо. – Gabriel

+0

Этот ответ использует квадратуру - это вариант здесь? Если необходимо использовать Монте-Карло, тогда код выше нуждается в нескольких изменениях. Хотелось бы, чтобы я понял ваши окончательные комментарии - предложение, начинающееся с «Я получаю значения, размещенные непосредственно над KDE ...», является для меня штопором. –

ответ

5

Красная площадь на участке является интеграл min(f(x), g(x)), где f и g являются ваши две функции, зеленого и синего цветов. Чтобы оценить интеграл, вы можете использовать любой из интеграторов из scipy.integrate (quad по умолчанию, я бы сказал) - или интегратор MC, конечно, но я не совсем понимаю.

+0

Так просто.Nice – wordsforthewise

+0

'min (f (x), g (x))' создает значение ValueError: значение истинности массива с более чем одним элементом неоднозначно. Используйте a.any() или a.all() '. Я не уверен, как его решить. Должно ли это быть 'min (f (x) .any(), g (x) .any())'? Но тогда он создает 'TypeError: 'numpy.bool_' объект не итерируется' – durbachit

0

Я думаю, что другим решением было бы умножить две кривые, а затем взять интеграл. Возможно, вы захотите сделать какую-то нормализацию. Аналогия орбитали перекрываются в области химии: https://en.wikipedia.org/wiki/Orbital_overlap

Смежные вопросы