2017-01-10 7 views
4

Ich möchte ein Konturdiagramm einer Kernel Density Estimation zeichnen, wo die KDE in jedem der gefüllten Konturbereiche integriert ist.Python - Integrieren 2D Kernel Density Estimation innerhalb von Konturlinien

Als Beispiel stelle ich mir die KDE von 2D-Daten berechnen:

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) 

Ich weiß, wie die ContourPlot des KDE zu ziehen.

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() 

Dieses Konturplot zeigt jedoch, wie hoch die Wahrscheinlichkeitsdichte in jedem der gefüllten Bereiche ist. Stattdessen möchte ich, dass die Handlung die Gesamtwahrscheinlichkeit anzeigt, die in jeden der gefüllten Bereiche fällt.

Antwort

1

Bitte beachten Sie, dass das Folgende nur korrekt ist, solange Ihre Konturen "monoton" sind, d. H. Innerhalb einer Konturlinie finden Sie nur Pixelwerte über der entsprechenden Konturlinie. Beachten Sie auch, dass wenn Ihre Dichte multipeaked ist, entsprechende Bereiche in einzelnen Peaks zusammengelegt werden.

Wenn dies wahr/akzeptabel ist, kann Ihr Problem gelöst werden, indem die Pixel nach Wert geordnet werden.

Ich weiß nicht, durch welche Heuristik Ihrer Plotprogramm seiner Kontur Ebene wählen, aber vorausgesetzt, Sie sie (in aufsteigender Reihenfolge, sagen) in einer Variablen namens ‚Ebenen‘ gespeichert haben könnten Sie so etwas wie

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] 
versuchen

Nun, damit Sie dieses verwenden können, muss Ihr Plot-Programm entweder erlauben, dass Sie die Konturetiketten frei wählen oder zumindest die Ebenen wählen, auf denen die Konturen abgelegt werden sollen. Im letzteren Fall, vorausgesetzt, es ist ein kwarg ‚Ebenen‘

# 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') 

Ich habe das von einem Ihrer Kommentare folgenden kopiert, um es sichtbar

Schließlich, wenn man wirklich will, müssen die Wahrscheinlichkeit in jedem gefüllten Bereich, das ist ein Workaround, der funktioniert: cb = fig.colorbar (cfset, ax = ax) Werte = cb.values.copy() Werte [1:] - = Werte [: - 1] .copy () cb.set_ticklabels (Werte) - Laura

+0

Vielen Dank. Obwohl die Antwort nicht vollständig funktioniert, bringt sie mich näher an die Lösung heran (zumindest in diesem speziellen Fall, in dem die Konturen monoton sind). Könnten Sie bitte klarstellen, was Sie tun, wenn Sie F [order] = 1 - F zuweisen? Danke – Laura

+0

Ich habe das Problem gefunden. Diese Lösung funktioniert, wenn man ax.contourf (xx, yy, (1-F), levels = new_levels) plottet. – Laura

+0

Großartig! Sie könnten also auch F [order] = 1 - F durch F [order] = F ersetzen und die andere Zeile unberührt lassen. Brauchen Sie noch einen Rat, was die F [order] = F-Linie eigentlich macht? –

Verwandte Themen