2017-01-10 13 views
4

Я хотел бы нарисовать контурный график оценки плотности ядра, где KDE интегрирован в пределах каждой области, заполненной контуром.Python - интегрировать оценку плотности ядра 2D в контурных линиях

В качестве примера, представьте, я вычисляю KDE 2D-данных:

data = np.random.multivariate_normal((0, 0), [[1, 1], [2, 0.7]], 100) 
x = data[:, 0] 
y = data[:, 1] 
xmin, xmax = min(x), max(x) 
ymin, ymax = min(y), max(y) 
xx, yy = np.mgrid[xmin:xmax:100j, ymin:ymax:100j] 
positions = np.vstack([xx.ravel(), yy.ravel()]) 
values = np.vstack([x, y]) 
kernel = st.gaussian_kde(values) 
f = np.reshape(kernel(positions).T, xx.shape) 

Я знаю, как рисовать contourplot в KDE.

fig = plt.figure() 
ax = fig.gca() 
ax.set_xlim(xmin, xmax) 
ax.set_ylim(ymin, ymax) 
cfset = ax.contourf(xx, yy, f, cmap='Blues') 
cset = ax.contour(xx, yy, f, colors='k') 
plt.show() 

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

ответ

1

Обратите внимание, что следующее верно только в том случае, если ваши контуры являются «монотонными», то есть внутри контурной линии вы найдете только значения пикселей выше соответствующего уровня контура. Также обратите внимание, что если ваша плотность является многосекущей, соответствующие области в отдельных пиках объединяются вместе.

Если это правда/приемлемо, ваша проблема может быть решена путем упорядочивания пикселей по значению.

Я не знаю, с помощью которого Эвристическое сюжет программа выбирает свои уровни контура, но при условии их сохранения (в порядке возрастания, скажем) в переменной, которая называется «уровнями» вы можете попробовать что-то вроде

ff = f.ravel() 
order = np.argsort(ff) 
fsorted = ff[order] 
F = np.cumsum(fsorted) 
# depending on how your density is normalised next line may be superfluous 
# also note that this is only correct for equal bins 
# and, finally, to be unimpeachably rigorous, this disregards the probability 
# mass outside the field of view, so it calculates probability condtional 
# on being in the field of view 
F /= F[-1] 
boundaries = fsorted.searchsorted(levels) 
new_levels = F[boundaries] 

Теперь, чтобы вы могли использовать это, ваша программа сюжета должна либо позволить вам свободно выбирать метки контура, либо, по крайней мере, выбирать уровни, на которых нужно контуров. В последнем случае, при условии, что есть kwarg «уровни»

# make a copy to avoid problems with in-place shuffling 
# i.e. overwriting positions whose original values are still to be read out 
F[order] = F.copy() 
F.shape = f.shape 
cset = ax.contour(xx, yy, F, levels=new_levels, colors='k') 

Я скопировал следующие из одного из ваших комментариев, чтобы сделать его более заметным

Наконец, если один хочет, чтобы действительно иметь вероятность в каждой заполненной области, это обходной путь, который работает: cb = fig.colorbar (cfset, ax = ax) values ​​= cb.values.copy() values ​​[1:] - = values ​​[: - 1] .copy () cb.set_ticklabels (значения) - Laura

+0

Спасибо. Хотя ответ не полностью работает, он приближает меня к решению (по крайней мере, в этом конкретном случае, когда контуры монотонны). Не могли бы вы пояснить, что вы делаете, когда назначаете F [order] = 1 - F? Спасибо – Laura

+0

Я нашел проблему. Это решение работает, если вы рисуете ax.contourf (xx, yy, (1-F), levels = new_levels). – Laura

+0

Отлично! Таким образом, вы, вероятно, могли бы также заменить F [порядок] = 1 - F на F [порядок] = F и оставить другую строку нетронутой. Вам все еще нужен совет о том, что на самом деле делает F [order] = F? –